2021年9月27日 星期一

Flutter wifi_iot範例加簡單註解

Flutter 好用套件wifi_iot
wifi_iot | Flutter Package (pub.dev)
目前版本^0.3.8 Published Sep 22, 2021

Plugin Flutter which can handle WiFi connections (AP, STA)

Becareful, some commands as no effect on iOS because Apple don't let us to do whatever we want...

雖然功能有限,但是做基本的物聯網APP開發已足夠,以下範例取自https://pub.dev/packages/wifi_iot/example 並且我已刪除WIFI STA內容

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:wifi_iot/wifi_iot.dart';
import 'dart:io' show Platform;


const NetworkSecurity AP_DEFAULT_SECURITY = NetworkSecurity.WPA;
const String AP_DEFAULT_SSID = "AP_SSID";
const String AP_DEFAULT_PASSWORD = "AP_PASSWORD";

//父狀態主頁(樣式+Wifi ststus)
class FlutterWifiIoT extends StatefulWidget {
FlutterWifiIoT({
Key? key
,
}) : super(key: key);

@override
_FlutterWifiIoTState createState() => _FlutterWifiIoTState();
//建立status
}

class _FlutterWifiIoTState extends State<FlutterWifiIoT> {


List<WifiNetwork?>?
_htResultNetwork; //WIFI可連清單
Map<String, bool>? _htIsNetworkRegistered = Map(); //WIFI SSID儲存清單與狀態

bool _isEnabled = false; //WIFI是否開啟
bool _isConnected = false; //WIFI是否已連接
bool _isWifiEnableOpenSettings = false; //是否被動開啟(Android 10)
bool _isWifiDisableOpenSettings = false; //是否被動關閉(Android 10)

final TextStyle textStyle = TextStyle(color: Colors.white);

@override
initState() {
WiFiForIoTPlug
in.isEnabled().then((val) {
_isEnabled = val;
});

WiFiForIoTPlugin.isConnected().then((val) {
_isConnected = val;
});

super.initState();
}


//使用函式庫載入WIFI列表
Future<List<WifiNetwork>> loadWifiList() async {
List<WifiNetwork> htResultNetwork
;
try {
htResultNetwork =
await WiFiForIoTPlugin.loadWifiList();
} on PlatformException {
htResultNetwork = <WifiNetwork>[]
;
}

return htResultNetwork;
}

//檢查是否已註冊SSID方法(存到Map ket,value)
isRegisteredWifiNetwork(String ssid) async {
bool bIsRegistered
;

try {
bIsRegistered =
await WiFiForIoTPlugin.isRegisteredWifiNetwork(ssid);
} on PlatformException {
bIsRegistered =
false;
}

setState(() {
_htIsNetworkRegistered![ssid] = bIsRegistered;
});
}

///Main body
Widget getWidgets() {
WiFiForIoTPlug
in.isConnected().then((val) {
setState(() {
_isConnected = val; //WIFI 為已連線狀態
});
});

// disable scanning for ios as not supported
//IOS手機無法支援WIFI清單功能
if (_isConnected || Platform.isIOS) {
_htResultNetwork = null;
}

//如果是Android, 且存在可連線網路, 否則不會載入WIFI清單
if (_htResultNetwork != null && _htResultNetwork!.length > 0) {
List<ListTile> htNetworks = <ListTile>[]
;

_htResultNetwork!.forEach((oNetwork) {
//將可連線網路跑一遍
PopupCommand oCmdConnect = PopupCommand("Connect", oNetwork!.ssid!);
PopupCommand oCmdRemove = PopupCommand("Remove", oNetwork.ssid!);

List<PopupMenuItem<PopupCommand>> htPopupMenuItems = [];

//加到popupMenu(選項為可連線)
htPopupMenuItems.add(
PopupMenuItem<PopupCommand>(
value: oCmdConnect
,
child: const Text('Connect'),
),
);

setState(() {
isRegisteredWifiNetwork(oNetwo
rk.ssid!);
//辨識這個SSID是否已儲存至系統,並在value中用布林表示
if (_htIsNetworkRegistered!.containsKey(oNetwork.ssid) &&
_htIsNetworkRegistered![oNetwork.ssid]!) {
htPopupMenuItems.add(
PopupMenuItem<PopupCommand>(
value: oCmdRemove
,
child: const Text('Remove'),
),//已儲存就可以提供刪除選項
);
}

htNetworks.add(
ListTile(
titl
e: Text("" +
oNetwo
rk.ssid! +
((_htIsNetworkRegistered!.containsKey(oNetwork.ssid) &&
_htIsNetworkRegistered![oNetwork.ssid]!)
?
" *"
: "")),//加入網路名稱,如果已註冊就標示*
trailing: PopupMenuButton<PopupCommand>(
padding: EdgeInse
ts.zero,
onSelected: (PopupCommand poCommand) {
//加入子元素(連線/刪除選項), 會判斷htPopupMenuItems傳進來的value
switch (poCommand.command) {
case "Connect":
WiFiForIoTPlug
in.connect(AP_DEFAULT_SSID,
password: AP_DEFAULT_PASSWORD,
joinOnce: true,
security: AP_DEFAULT_SECURITY);
break;
case "Remove":
WiFiForIoTPlug
in.removeWifiNetwork(poCommand.argument);
break;
default:
break;
}
}
,
itemBuilder: (BuildContext context) => htPopupMenuItems,
),
),
);
});
});

return ListView(
padding: kMaterialListPadding
,
children: htNetworks,
);
} else {
//如果是IOS, Android搜尋結果為0時進入這邊
return SingleChildScrollView(
chil
d: SafeArea(
chil
d: Column(
children: Platfo
rm.isIOS
? getButtonWidgetsForiOS()
: getButtonWidgetsForAndroid()
,
),
),
);
}
}

List<Widge
t> getButtonWidgetsForAndroid() {
List<Widget> htPrimaryWidgets = <Widget>[]
;

WiFiForIoTPlugin.isEnabled().then((val) {
setState(() {
_isEnabled = val;
});
});

if (_isEnabled) {
htPrimaryWidgets.addAll([
SizedBox(height: 10),
Text("Wifi Enabled"),
MaterialButton(
color: Colo
rs.blue,
child: Text("Disable", style: textStyle),
onPressed: () {
WiFiForIoTPlug
in.setEnabled(false,
shouldOpenSettings: _isWifiDisableOpenSettings
)
;
},
),
]);

WiFiForIoTPlugin.isConnected().then((val) {
setState(() {
_isConnected = val;
});
});

if (_isConnected) {
//已經連上Wifi, 回傳連線資訊
htPrimaryWidgets.addAll(<Widget>[
Text("Connected"),
FutureBuilder(
future: WiFiForIoTPlug
in.getSSID(),
initialData: "Loading..",
builder: (BuildContext context, AsyncSnapshot<String?> ssid) {
return Text("SSID: ${ssid.data}");
}),
FutureBuilder(
future: WiFiForIoTPlug
in.getBSSID(),
initialData: "Loading..",
builder: (BuildContext context, AsyncSnapshot<String?> bssid) {
return Text("BSSID: ${bssid.data}");
}),
FutureBuilder(
future: WiFiForIoTPlug
in.getCurrentSignalStrength(),
initialData: 0,
builder: (BuildContext context, AsyncSnapshot<int?> signal) {
return Text("Signal: ${signal.data}");
}),
FutureBuilder(
future: WiFiForIoTPlug
in.getFrequency(),
initialData: 0,
builder: (BuildContext context, AsyncSnapshot<int?> freq) {
return Text("Frequency : ${freq.data}");
}),
FutureBuilder(
future: WiFiForIoTPlug
in.getIP(),
initialData: "Loading..",
builder: (BuildContext context, AsyncSnapshot<String?> ip) {
return Text("IP : ${ip.data}");
}),
MaterialButton(
color: Colo
rs.blue,
child: Text("Disconnect", style: textStyle),
onPressed: () {
WiFiForIoTPlug
in.disconnect();
},
),
CheckboxListTile(
title:
const Text("Disable WiFi on settings"),
subtitle: const Text("Available only on android API level >= 29"),
value: _isWifiDisableOpenSettings,
onChanged: (bool? setting) {
if (setting != null) {
setState(() {
_isWifiDisableOpenSettings = setting;
});
}
}
)
//Android API29以上可以被動接收WIFI info
]);
} else {
//未連上WIFI, 顯示WIFI搜尋
htPrimaryWidgets.addAll(<Widget>[
Text("Disconnected"),
MaterialButton(
color: Colo
rs.blue,
child: Text("Scan", style: textStyle),
onPressed: () async {
_htResultNetwork = await loadWifiList();
setState(() {});
},
),
CheckboxListTile(
title:
const Text("Disable WiFi on settings"),
subtitle: const Text("Available only on android API level >= 29"),
value: _isWifiDisableOpenSettings,
onChanged: (bool? setting) {
if (setting != null) {
setState(() {
_isWifiDisableOpenSettings = setting;
});
}
}
)
])
;
}
}
else {
//WIFI設定未開啟
htPrimaryWidgets.addAll(<Widget>[
SizedBox(height: 10),
Text("Wifi Disabled"),
MaterialButton(
color: Colo
rs.blue,
child: Text("Enable", style: textStyle),
onPressed: () {
setState(() {
WiFiForIoTPlug
in.setEnabled(true,
shouldOpenSettings: _isWifiEnableOpenSettings
)
;
});
},
),
CheckboxListTile(
title:
const Text("Enable WiFi on settings"),
subtitle: const Text("Available only on android API level >= 29"),
value: _isWifiEnableOpenSettings,
onChanged: (bool? setting) {
if (setting != null) {
setState(() {
_isWifiEnableOpenSettings = setting;
});
}
}
)
])
;
}

return htPrimaryWidgets;
}

List<Widge
t> getButtonWidgetsForiOS() {
List<Widget> htPrimaryWidgets = <Widget>[]
;

WiFiForIoTPlugin.isEnabled().then((val) => setState(() {
_isEnabled = val;
}));

if (_isEnabled) {
htPrimaryWidgets.a
dd(Text("Wifi Enabled"));
WiFiForIoTPlugin.isConnected().then((val) => setState(() {
_isConnected = val;
}));

String? _sSSID;

if (_isConnected) {
//IOS 顯示連線(SSID)
htPrimaryWidgets.addAll(<Widget>[
Text("Connected"),
FutureBuilder(
future: WiFiForIoTPlug
in.getSSID(),
initialData: "Loading..",
builder: (BuildContext context, AsyncSnapshot<String?> ssid) {
_sSSID = ss
id.data;

return Text("SSID: ${ssid.data}");
}),
]);

if (_sSSID == AP_DEFAULT_SSID) {
//IOS連上指定SSID
htPrimaryWidgets.addAll(<Widget>[
MaterialButton(
color: Colo
rs.blue,
child: Text("Disconnect", style: textStyle),
onPressed: () {
WiFiForIoTPlug
in.disconnect();
},
),
]);
} else {
//IOS未上指定SSID, 提供按鈕直接連
htPrimaryWidgets.addAll(<Widget>[
MaterialButton(
color: Colo
rs.blue,
child: Text("Connect to '$AP_DEFAULT_SSID'", style: textStyle),
onPressed: () {
WiFiForIoTPlug
in.connect(AP_DEFAULT_SSID,
password: AP_DEFAULT_PASSWORD,
joinOnce: true,
security: NetworkSecurity.WPA);
},
),
]);
}
}
else {
//IOS未上網路, 一樣提供按鈕直接連
htPrimaryWidgets.addAll(<Widget>[
Text("Disconnected"),
MaterialButton(
color: Colo
rs.blue,
child: Text("Connect to '$AP_DEFAULT_SSID'", style: textStyle),
onPressed: () {
WiFiForIoTPlug
in.connect(AP_DEFAULT_SSID,
password: AP_DEFAULT_PASSWORD,
joinOnce: true,
security: NetworkSecurity.WPA);
},
),
]);
}
}
else {
//IOS WIFI是關閉的, 給設定可以硬連
htPrimaryWidgets.addAll(<Widget>[
Text("Wifi Disabled?"),
MaterialButton(
color: Colo
rs.blue,
child: Text("Connect to '$AP_DEFAULT_SSID'", style: textStyle),
onPressed: () {
WiFiForIoTPlug
in.connect(AP_DEFAULT_SSID,
password: AP_DEFAULT_PASSWORD,
joinOnce: true,
security: NetworkSecurity.WPA);
},
),
]);
}

return htPrimaryWidgets;
}

@override
Widg
et build(BuildContext poContext) {
return MaterialApp(
title: Platfo
rm.isIOS ?
"WifiFlutter Example iOS" : "WifiFlutter Example Android",
home: Scaffold(
appBa
r: AppBar(
title: Platfo
rm.isIOS
? Text('WifiFlutter Example iOS')
: Text('WifiFlutter Example Android'),
actions: _isConnected
? <Widget>[
PopupMenuButton<String>(
onSelected: (value) {
switch (value) {
case "disconnect":
WiFiForIoTPlug
in.disconnect();
break;
case "remove":
WiFiForIoTPlug
in.getSSID().then(
(val) => WiFiForIoTPlug
in.removeWifiNetwork(val!));
break;
default:
break;
}
}
,
itemBuilder: (BuildContext context) =>
<PopupMenuItem<String>>[
PopupMenuItem<String>(
value:
"disconnect",
child: const Text('Disconnect'),
),
PopupMenuItem<String>(
value:
"remove",
child: const Text('Remove'),
),
],
),
]
:
null,
),
body: getWidgets(),
),
);
}
}

class PopupCommand {
Stri
ng command;
String argument;

PopupCommand(this.command, this.argument);
}

//頁面樣式(無狀態)
class CardDemo extends StatelessWidget {
final TextEditingController _textFieldController = TextEditingController();
final List listData = [
{
"title": "物料站 1 ",
"context": "相關編號....",
},
{
"title": "物料站 2 ",
"context": "相關編號....",
}
]
;

@override
Widg
et build(BuildContext context) {
return ListView(
childre
n: listData.map((value) {
return Card(
margi
n: EdgeInsets.all(10), //外邊距
child: Column(
//縱向排列元件
children: <Widget>[
ListTile(
titl
e: Text(value["title"], style: TextStyle(fontSize: 28)),
subtitle: Text(value["context"],
overflow: TextOverflow.ellipsis,
maxLines: 2, //文字溢位
style: TextStyle(fontSize: 18, color: Colors.black)),
onTap: () => _displayDialog(context),
),
],
),
);
}).toList(),
);
}

_displayDialog(BuildContext context) async {
return showDialog(
context: context
,
builder: (context) {
return AlertDialog(
titl
e: Text('Material Password'),
content: TextField(
controlle
r: _textFieldController,
textInputAction: TextInputAction.go,
keyboardType: TextInputType.numberWithOptions(),
decoration: InputDecoration(hintText: "Password"),
),
actions: <Widget>[
new FlatButton(
child:
new Text('Cancel'),
onPressed: () {
Navigat
or.of(context).pop();
},
),
new FlatButton(
child:
new Text('Comfirm'),
onPressed: () {
_displayDialog2(context)
;
},
)
]
,
);
});
}

_displayDialog2(BuildContext context) async {
return showDialog(
context: context
,
builder: (context) {
return AlertDialog(
titl
e: Text('Material Name'),
content: TextField(
controlle
r: _textFieldController,
textInputAction: TextInputAction.go,
keyboardType: TextInputType.numberWithOptions(),
decoration: InputDecoration(hintText: "Password"),
),
actions: <Widget>[
new FlatButton(
child:
new Text('Cancel'),
onPressed: () {
Navigat
or.of(context).pop();
},
),
new FlatButton(
child:
new Text('Comfirm'),
onPressed: () {
Navigat
or.push(context,
MaterialPageRoute(builder: (context) => XDChooseWifi()));
},
)
]
,
);
});
}

} 

2021年6月18日 星期五

109社團負責人研習心得

  2020年暑假,很榮幸獲補助參加救國團北大服所舉辦的研習會。因109社研參加對象為全國大學的社團幹部,各個來歷都不小,因此,要與各大領導專長的同學相處,不知道會出現甚麼火花,個人除了緊張外,內心更充滿說不出的膨湃感。這五天我要在研習中學習組織的經營管理、規劃活動的創新及全面性、觀察活動及交流經驗等,期待與夥伴有好的相處,結交志同道合的朋友。

  第一次參加北大服的活動,我感到很有系統化,分享具特色的地方。報到當天有人員進行檢疫,分成男女兩隊,由嚴肅的日值進行報到人流管控,這令我感到專業,很快能使學員進入狀況。報到處第一站進行資料查核與簽到、發放資料袋(有寫學員代碼、寢室號碼、餐桌號碼);第二站檢查行前作業;第三站進行選課,然後才進入始業式會場。始業式由活動輔導員持續炒熱氣氛,帶著學員互動交流,對比我以前參加的營會,學員很快就拋開尷尬。

  早晨有重要的升旗儀式,令人憶起國小時的國歌升旗歌,由一位駐會教授擔任主席,禮成前會進行勉勵與頒獎。用餐時間是圍桌吃飯,輔導員會在門口呼喊創意的餐前口號,覺得新奇又有趣,用餐前由日值指揮,全員會肅坐、飯前致謝、說明飯後事項、呼喊創意口號後才開始用餐。晚上的活動主要分成三塊,家庭會議、星光夜語與心靈晚課,家庭會議是各組與小隊輔的交流時間;星光夜語則是與每組的輔導教授交流;心靈晚課會撰寫心得本、練習營歌與品格故事分享。

  在課程部分,第一天由救國團的葛主任來授課,他為我們分享好青年的定義:夠獨立、有人品、有貢獻,總結我們得充實自己的知識,擁有獨立思考才能做出決定,然後不要害怕做出錯誤的決定,要學習正面的思考,能夠服務別人也幫助幫人。下午和隔天早上是探索教育課程,一開始老師帶領我們認識彼此,建立共同默契,接著會透過各樣的活動,來學習策略規劃、問題解決的能力,每次活動後,必定有個不乏味的分享時間,討論我們在活動中學到的東西,其中都對社團經營具有含意,從中很多夥伴會表達內心的想法,這就是很棒的交流。

  第二天有社團經營Q&A世界咖啡館,這個課程很新奇,我們輪流換桌,並針對社團經營方式來審視,提供改進的方法。眾多問題中最讓我印象深刻,如何妥善的運用社團資源,分成了財務、器材、跟人事,我個人中意器材這個項目 因為目前參加的社團具有大量的器材較不容易管理。過程從一開始的大問題,再來聚焦提出方案,在各個學員絞盡腦汁後,最後有統整的發表分享,雖然過程很緊湊,但內容足夠紮實且多元,頗有參考價值。下午時間,蔡志賢教授來分享新世代社團所需有的思維,講師在課程中提到豐富的經驗故事,整個過程很生動吸引人,講師提到:「你要有想法,要有自己的思維,而不是被現有的框架制約。」希望我們成為有想法的領導者。晚上是競賽晚會,會展示各組的隊旗與隊呼,並發表團隊的表演,讓我憶起我們短短時間內分組並協力完成的成果,由於各位夥伴大多有不少的社團經驗,在須臾片刻內迅快且有默契地完成這些設計,成果發表也有不錯的表現。

  第三天早上的講師教我們製作創意企劃,這個課程帶我們有系統組織的發想活動,分組過程中,我們從活動的宗旨設計出活動名稱,透過心智圖的方式,由人事時地物出發,一步步深入活動的細節,最後我看到各組的展示都很吸睛,期待回到社團,也靠著這樣的工具來弄新企畫。下午則由行銷公司的學長來分享影像運用與行銷技巧,這個課程打破我原本設想的內容,講師用貼切的方式來帶我們入門攝影構圖與剪輯,內容有實作也有探討,在由淺入深之下,每個人都能很快的吸收,也展開我對於社群行銷的視野。用餐前有團康的遊戲時間,這和探索教育有點不同,探索教育會強調活動後收獲並彼此交流想法,團康遊戲就需盡全力爭取分數,同樣彼此融入、集思廣益。這幾天以來的星空夜語時刻,教授帶著我們發表意見與想法,實際更認識夥伴的學校與社團,這一天輔導教授透過圖卡,讓我們每位組員輪流分享圖片與本研習連結所帶來的感受,也有感性的發表時間。

  第四天早晨是成果發表會,大家卯足心力,拋棄睡意來進行,這一次因為籌備的時間短,其實光我負責的器材這邊就面臨很多問題,慶幸的是,我們大家恰好發揮專長補上缺失,在危機處理方面,夥伴們在這方面也都處理得很恰當。接著由台大副校長來分享國際視野的課程,她的主軸由我、我們、他們、你們做出發,分享她的經驗、我們國家的邦交地位、他國的貿易關係、激勵學員的理想和目標等,她告訴我們,沒有行不行,只有做不做,做到才是王道,知道只是基礎。接下來的時間是為著舞會所做準備,實際內容就不多闡述,研習中也安排國標舞的課程,教學華爾滋以及恰恰舞步。

  這個研習營的活動對象實在特殊,同屬性的人聚在一起,不是我想像中那樣容易發生意見爭執,在我小隊相處的過程中,有一股像家人般的默契,針對彼此的過失能給予包容並提出建議,很難在其他營隊配對如此協調完美的組合,這是我目前還在回味的主要原因。在活動籌備方面,靠這短短的時間,不能實際套用在社團的活動籌備,籌備一定要花時間檢查各個細節、分配工作並追蹤。最後,感謝北大服一直舉辦這樣的研習活動,讓全台大專院校的社團能彼此連結,也用心的設計課程內容,各個紮實又不失專業度,我想唯一的缺失其實就是過於系統化,期待未來活動可以加入更多的創新,讓過程比較輕鬆好玩,避免過於死板。活動性質偏增進各校社團聯繫,對於積極拓展外校合作的學生會、社團,我會強烈推薦給同學參與,不管如何,如此高規格、內容充實的營隊偏少,很推薦同學來見識一下,相信會對社團經營有不一樣的想法。



2021年5月26日 星期三

驚爆13天電影觀後心得

  這周國防老師推薦我們電影「驚爆十三天」,昨天晚上買好晚餐就跟室友一起看,由於這部片子是2000年的,有點擔心室友會看一看就跑上樓。有趣的是,最後我們倆反而開始討論、回味劇情,甚至查起歷史上這起古巴飛彈的危機,可以說是今年難得看到的好電影。

  整部電影除了有軍事政治,更加入親情的元素,這是我最喜歡的地方,電影主角是當時美國總統甘迺迪的專聘顧問,當時在偵察機發現蘇聯在古巴佈置導彈,高官內層就開會討論,總統每個面向都聽過一遍,有人認為要空襲打掉飛彈、有人認同要地面展開攻擊,沒有一個更好的方法,電影主角也很同理總統的現況,關心與支持他,也在很多關鍵時刻制止高官強勢對總統的決策干擾,最後是提出能妥協的方案-封鎖古巴線。

  這是一個官僚議價模式,官僚內部每個人都有自己有利的立場與想法,這非常難做理性的思考,所以在短期的解決方案,總統選擇這個利益調和下的結果。印象很深刻的是他在全民面前所報的新聞稿,在他的助手與潤飾之下,我很佩服講的內容,因每字每句都能重點詳述人事時地物,這肯定的語氣看的出來他承諾給人民一個保障與交代。發展到最後就是歷史上的黑色星期六,兩國面對棘手的危機情勢,總統反而冷靜且果決的下處理,軍隊服從總統命令,當時沒有馬上進行交戰,而是採用孫子兵法的外交手段,才可能化解這次的危機。

  我相信一個國家沒有這些官僚是無法運作的,而沒有言論自由是侵犯權益的,在這樣的模式下,怎麼做好利害分析、包容同理彼此(事後美國與蘇聯更建立了熱線與核彈密碼機制),我看到國際的情勢衝突事情是可以避免的。

2019年4月30日 星期二

MT7697拍手兩次 關滅燈(改編)


聲音感測模組測試可以到

http://yhhuang1966.blogspot.com/2017/10/arduino.html


以下是我改編過的拍手兩次..原版似乎不太準(Using Arduino IDE)
請在自行修正參數

#define micPin A0
#define ledPin 2
boolean ledState = false; //紀錄 LED 狀態,預設為打開
int micVal;  //紀錄偵測到的音量

long current = 0; //紀錄目前過門檻時戳
long last = 0; //紀錄上次過門檻時戳
long diff = 0; //紀錄前後兩次時間差
int count = 0; //紀錄已偵測到的次數

void setup() {
  pinMode(ledPin, OUTPUT);
  Serial.begin(115200);
}
void loop() {
  if (analogRead(micPin) > 2000) {  //若超過門檻值
    delay(50);
    if (analogRead(micPin) > 2000 ) {
      Serial.println(analogRead(micPin));
      current = millis(); //紀錄目前時戳
      count++;  //次數
    }
    if (analogRead(micPin) > 2000 && count >= 2) {  //若次數已達 2 次
      diff = current - last; //計算前後兩次時間差
      Serial.println("disdance="+String(diff));
      if (diff > 300 && diff < 1500) {
         Serial.println("change");
        ledState = !ledState;
        count = 0;
      } else {
        count = 1; //太久或太慢
      }    
    }
    last = current; //以目前時戳更新上次時戳
    if (ledState) {
      digitalWrite(ledPin, HIGH);
    }else {
      digitalWrite(ledPin, LOW);
    }
  }

  delay(50);
}

2019年4月2日 星期二

RGB LED 不會亮/顏色總是混合到..

因為還有作業 不打很多了.. 最近摸了RGB LED,課堂上參考葉難的教學
http://yehnan.blogspot.com/2013/01/arduinorgb-led.html

一開始不會亮喔,我試了很久,怕接反會燒掉,後來還是試了,的確要把它給接反(最長那根改通電3.3V) 但雖然可以亮,我要馬還是亮錯顏色,且顏色會和在一起,這個問題該不會是燈泡壞了吧 = =

後來看到這句話
RGB LED有四支腳,我買的是共陰極,其中最長的腳要接地,其他三支腳分別控制R、G、B色彩。

看來搜尋看看共陽極好了! 我找到這個MT7697搭配blocklyduino的教學 
https://docs.labs.mediatek.com/linkit-7697-blocklyduino/a04-rgb-led-12879766.html
腳位1 的接到 3.3V 的電源, 腳位 2 / 3 / 4 接到數位輸出腳位

確定我的是共陽極了! 它很特別,你通電給他(high)它才不會亮
所以,不會亮把它改成此教學的範例即可。


因此,共陽極要改變顏色的輸出變化,也是要用255減掉(改自葉難教學)

#define LEDR 15
#define LEDG 16
#define LEDB 17

void setup() {
  pinMode(LEDR, OUTPUT);
  pinMode(LEDG, OUTPUT);
  pinMode(LEDB, OUTPUT);
  RGB_Led(0,0,0); //turnOff
}

void RGB_Led(int r, int g, int b) {
  analogWrite(LEDR, 255 - r);
  analogWrite(LEDG, 255 - g);
  analogWrite(LEDB, 255 - b);
}

// 每隔一秒改變LED的顏色,紅、綠、藍
void loop() {

  RGB_Led(0,0,0); //turnOff
  RGB_Led(255,0,0); //Red
  delay(1000);

  RGB_Led(0,0,0); //turnOff
  RGB_Led(0,255,0); //Green
  delay(1000);

  RGB_Led(0,0,0); //turnOff
  RGB_Led(0,0,255); //Blue
  delay(1000);
}

希望有幫助到大家,有問題歡迎留言喔

2019年1月31日 星期四

大學學校歷程分享(大一)

        ㄚㄚ...隔了好一段時間才來分享近況了,可能是專題壓力小很多,加上我最近大小鬼縱走結束,還有時間來PO文- > 來個時光回朔+簡短分享  我會慢慢更新上來

大一上

一上最終課表
開學一開始,真的覺得我的專題老師敢有壓迫感,很恐怖,就多選了管理學(當個搓合期吧?) 但管理真的算好過了,雖然很多學長姐都多是大刀,但我們這學期真的算不錯,老師期末出國,不用穿正式的衣服上台報告,期中期末筆試加書面報告。

當初擔心的企業資訊網路其實就是在上CCNA的課本,個人認為老師是很有趣...不過到後期不有趣了,漏接一些資訊導致作業沒有做到,這裡很感謝好心的學長幫忙,也給我考古題進行練習。

Android上到後面,真的會深入很多,雖然老師幾乎照著網路上教材再帶,因為個人物件導向的基礎還不是很夠吧! 繼承、新物件的一些原理、方法的類型、介面根本都搞不懂,不過期中我還是有盡力的把他完成(旅遊景點App),還記得有用到靜態方法。期末因為準備考試 報告時間關係,還有電腦的問題,轉戰到網咖進行一日期末衝刺,那次真的就是移花接木了,用到的技術也不少(下午6點開始,開了8小時...)再來那天是寒流來的第一天 = =我半夜做完回宿舍洗冷水澡睡覺,隔天報告蠻順利的把它完成了,作品是一個備忘錄的App,之後真的好好好自學好。

其它課,計概是真的不錯,我們老師會給我們術科的練習,範圍很廣,可以摸到很多好玩的軟體及技術;溝表課就是拍影片 30分鐘加每周電影心得+期末申論;創創是由技優的老師帶我們的課程,裡面有創意的發想、做冰棒棍、3D列印筆的體驗等。

大一下


一下最終課表

大一下感覺是最硬的時期了,修了離散數學跟一堆實作課...

物件導向程式設計這門硬了些,上課內容很有料,有足夠的練習,廣度及深度個人認為都有到位,這門體驗很多物件導向的奧秘,解開多時的疑惑。除了對物件導向有基本的認識,老師也上了JSF,期末要做一個Java Form程式 及 一個JSF網站來向同學展示。期末作業是有範本的,但是我一直很想做看看自創程式的開發,那個時候真的搞死自己,半個月Coding 都過不正常的日子。

資訊網路應用上的是linux...果真填補沒修道到課的遺憾了@@ 另外這門主要針對server服務去安裝,去介紹它的架構,很輕鬆很好玩,裝好環境就複製貼上語法,不過原理我是真的有認真在聽,上網作功課,期末第一個拿100的科目。內容有安裝DNS(Bind9)、Web server、DB、FTP server、Mail server等,學好DNS同時也是我加入網路組技術組的重要技術。

多媒體系統聽說未來不會開了,加上陪同學上課,決定很久。這門課的老師是AI權威,不過上這種簡單的媒體剪輯應用(有看過教學課綱應該就很少會選),會上movie maker、GIMP之類的,不過我主要是衝著影像技術及AR來,除了講解那些MAKER GIMP外,其它課真的可以學到東西,除了影像技術,還有讚嘆的模擬人聲技術(訊飛)、EASY AR可以簡單建構AR模型。不過期末我也是搞得很操,做一個校園的AR解謎遊戲,不過也順利的完成它了!

還有一門可怕的資管導論,除了上課,我們還要幫忙老師做燕巢在地有機農產銷售的USR計畫,去探訪市集,賣棗子、芭樂的
一些周邊產品,我們有同學做了芭樂冰淇淋、果凍(超多元)。而我們是做吉祥物設計,那隻在三角形左邊的人偶叫-呱霸,而這個設計從組長一開始隨手亂畫,到期末一直陪伴我們。比較想抱怨的是,我真的沒有甚麼美工能力,最後搞得我都在設計,海報、名片,還有期末的PPT版面,不過真的也學到很多,體驗很多啦...

視窗程式上C# 其實是蠻無壓力的課,課程內容跟大一程式差不多,期末做一個Pos系統;科技與社會同以前的溝表課;專題研討課就是聽講座,期末繳交一篇心得,是較為輕鬆。

專題課程(技優生)

這個問題..大一一開始真的是怕爆了,每次要跟老師Meeting 就超級緊張,有時候都在在門口站一陣子,想好內容,甚至要寫在紙上,怕漏講,老師不開心。我在專題課程裡面是學有關物聯網的技術,從一開始的平台Arduino轉戰到MTK的開發版,學了Python GUI還有MQTT等技術,比較頭痛的還是在硬體跟軟體間的bug已經校正、優化處理。這些東西做了一年,老師也找了不少廠商來看我的作品,到現在已經申請過兩個計畫,雖然我一開始真的不覺得有這個機會不多...每期末我們都有成果發表,不過老師的考量下,我先展示高中畢業所完成的網站,踏浪。直到現在,我可以跟實驗室的學長姊融入,也比較不怕老師?不過皮還是得盯緊。說真的 老師真的還是很Nice 會關心我們的,真的覺得 很幸福了!


社團

大一上一開始加入了系排,不過那真的很超.. 不過很感謝那時候的訓練,我之後體育的排球可以順利的考滿分🤣 之後,我加入了志工性社團,那次之後,週末幾乎都有固定行程-才藝班,會去上爵士鼓的教學,同時也去帶小朋友。寒假暑假就不無聊了,有冬令營夏令營可以帶。

總結一下,大一真的很精彩,說真的,一開始以為玩不到社團了,老師的關係?不過老師還是放手讓我去體驗想做的事,不過專題還是要有進度的🤔 想當初我在營隊住宿時,半夜還是一邊做專題的怪咖。現在也加入山社,短短期間,我才跑兩個活動,學長就放心帶我去今年初的10天大小鬼縱走活動,真的很難得。我也認識很棒的學校室友們,關心我帶我玩,一起熬夜吃外送,現在的室友也很棒,重點房間還有廚房,可以開始鑽研一下廚藝了!課業方面到目前為止不太是個問題,可能是那個創新創業的相關模組還有跨領域的課比較麻煩一點,以課程來說都是有收穫的。

技優課程規劃歷程

      本屆學校資管系新增技優人才的特殊課程規劃,原有五位同學,開學後我和另外的同學成功在技優選拔中脫穎而出(新增我們兩位)。技優學程的選修幾乎都衝到通識、必修...經過我和他的討論下,分析每堂課的能力需求,最後決定的大一上學期的課程如下,可能除了會計學以外,其他課都照舊,會計學那堂則去修看看資訊科學與Python。
      資訊科學與Python的課有一些大數據分析的部分,這堂課除了要學會Python外,操作電腦需使用UNIX、一些Linux的指令,還需要機率與統計的概念。本學期程式要接觸Java要修理論課,又要為這堂課去安裝環境、提早學Python還有操作UNIX等等,不過我覺得這也是磨練我們的機會,也不一定選得上阿 = =

最後,我們決定去系辦討問清楚,這是我們最後的課表(微積分改Android實作,會計則改為企業資訊網路)。
不過呢....可以請大家看看這兩本課本。超級厚阿。不過,我們還是抱著必死的決心去試聽看看了。

聽完Android老師的課後,那希望的火終於點燃了,雖然我們java基礎沒有很強,但是老師那仔細、認真的教學方式,讓我們都大開眼界,這堂課真的沒有白選~~

倒是企業資訊網路的課程還未知,真的希望也能應付得來啊。

經我們細心研究後發現,技優學程沒有想像中這麼完美,希望我們現在搭配是正確的,我的高中老師也尊重我們選擇。






docker-mac Desktop清除容器log

 最近Docker遇到這個問題 Error grabbing logs: invalid character '{' looking for beginning of object key string. 建議的解法是刪除整個log檔,大家可以參考以下教學 htt...