有5個開關,一開始會隨機選出一個當做正確答案,然後讓使用者猜猜看按按看哪個才是對的,若按中正確的就點亮LED;另外有個開關是重置鍵。
接線:
從Arduino板的5V與GND接到麵包板。
Arduino腳位2、3、4、5、6、9,各接到開關的右上腳,
開關的右下腳接電阻後接地,
開關的左下腳接5V。
Arduino腳位8接電阻後接LED長腳,LED短腳接地。
程式碼如下(可到這裡下載):
/* inpin1到inpin5,讓使用者猜猜哪個才是正確的 */
int inpin1=2;
int inpin2=3;
int inpin3=4;
int inpin4=5;
int inpin5=6;
int led=8; /* LED的腳位 */
int inpinReset = 9; /* 重置 */
int randnum; /* 代表哪個才是正確答案 */
/* 重置,以亂數從新選出一個正確答案 */
/* 並熄滅LED */
void reset() {
randnum = random(1, 6);
digitalWrite(led, LOW);
Serial.print("randnum=");
Serial.println(randnum);
delay(500);
}
void setup() {
pinMode(inpin1, INPUT);
pinMode(inpin2, INPUT);
pinMode(inpin3, INPUT);
pinMode(inpin4, INPUT);
pinMode(inpin5, INPUT);
pinMode(led, OUTPUT);
pinMode(inpinReset, INPUT);
Serial.begin(115200);
reset();
}
void loop() {
/* 檢查使用者有沒有按下正確的答案(開關) */
switch (randnum) {
case 1:
if(digitalRead(inpin1) == HIGH){
digitalWrite(led, HIGH);
Serial.println("inpin1");
}
break;
case 2:
if(digitalRead(inpin2) == HIGH){
digitalWrite(led, HIGH);
Serial.println("inpin2");
}
break;
case 3:
if(digitalRead(inpin3) == HIGH){
digitalWrite(led, HIGH);
Serial.println("inpin3");
}
break;
case 4:
if(digitalRead(inpin4) == HIGH){
digitalWrite(led, HIGH);
Serial.println("inpin4");
}
break;
case 5:
if(digitalRead(inpin5) == HIGH){
digitalWrite(led, HIGH);
Serial.println("inpin5");
}
break;
}
/* 若按下inpinReset就重置 */
if(digitalRead(inpinReset) == HIGH){
Serial.println("inpinReset");
reset();
}
}
上面這份程式碼,還有很多可以改進的地方。
首先是亂數的部分,應該要先用randomSeed(analogRead(0)),才不會每次產生出來的亂數序列都是一樣的。
然後是switch的部份,可利用陣列儲存腳位,就不需要重複寫那麼多個case了。
另外,開關會有bounce問題,不過就這裡的情況來說,沒關係。
另外,可以增加「最多猜三次」這樣的行為,三次都猜錯後就失敗、重置。
可以增加揚聲器,發出猜對、猜錯的音效。
萬分感謝
ReplyDelete請問一下,我想寫一個程式,然後有兩個不同的執行迴圈,我想在序列埠監控視窗輸入不同數字然後執行相對應的迴圈,本來想說試試看switch case 但我用了以後程式卻只能執行一次,而不能重複持續迴圈,可否給小弟一點如何寫這程式的提點,拜託了!
ReplyDelete大概是這樣子吧
Deleteint x = 0;
void loop(){
switch(x){
case 0:
break;
case 1:
迴圈一
break;
case 2:
迴圈二
break;
}
}
從序列埠接收數字,然後設定全域變數x,
根據x的值,執行相對應的迴圈。
第一次接觸有個地方看不太懂
ReplyDelete從Arduino板的5V與GND接到麵包板,接在上面的正負極是要幹嘛?
看沒有其他接線接過去,還是說上面的正負極和下面的正負極是相通的?
煩請指教
是的,如你所說。文中照片沒有秀出來。
Delete如果要把上面的按鈕改成紅外線遙控器上的按鈕要怎麼辦
ReplyDelete請參考
DeleteArduino練習:紅外線傳送與接收
http://yehnan.blogspot.tw/2013/05/arduino.html
請問這電阻是接多少的阿?
ReplyDelete圖片看不太出來
謝謝
開關的電阻是10k,
DeleteLED的電阻是220。
請問這電阻是怎麼知道該使用多少的啊?
Delete如果我沒有這些可以用哪些電阻來代替嗎?
謝謝
請參閱 Arduino小知識:為什麼LED需要串聯的電阻值是220 ohm?
Deletehttp://yehnan.blogspot.tw/2012/03/arduinoled220-ohm.html
以這篇文章裡的電路而言,220 ohm可以換成150~300,應該都可以,不過會影響LED亮度。10k ohm可以換成8k~12k,應該都可以。
亂數的部分,應該要先用randomSeed(analogRead(0))
ReplyDelete請問這句能否在解釋的詳細一點呢
遇到亂數一直都跑同一個的問題
謝謝~
Arduino提供的是假亂數(pseudo-random),
Delete你把它想像成:Arduino內建有一長串的亂數值,呼叫random時、預設會從第一個拿出來給你,下次呼叫random時會拿第二個給你,若如此,每次都會得到相同的亂數序列。
所以要先呼叫randomSeed,作用是跳到一長串亂數值的某個位置,然後從該位置開始。
當腳位A0沒有接東西時,呼叫analogRead讀取的話,會讀到空氣,值不定。
了解!!
Delete非常感謝
請問一下 如果不只要隨機一個亂數
ReplyDelete想要改成每次隨機個數不同
不知能怎麼改呢 謝謝!!
> 每次隨機個數不同
Delete你問的是這一篇嗎?
你說的是需求,不是問題。
對 我的意思是要每次隨機個數不同
Delete好像找不到這一篇的文章耶~
不知道要怎麼改才有辦法達成
謝謝
喔,了解。
Delete請參考這篇
Arduino練習:Simon Says請你跟我這樣做
http://yehnan.blogspot.tw/2012/02/arduinosimon-says.html
請問一下,不能讓每個開關共電阻嗎?
ReplyDelete這樣不就互相影響?
DeleteThis comment has been removed by the author.
ReplyDelete只要跳到控制馬達的部分就好,看不太懂隨機的寫法,馬達該怎麼控制我已經知道了
Delete不斷地呼叫random(1, 3);取得介於1~3之間的亂數,
Delete使用switch根據該亂數值,執行你想要的馬達控制指令。
#include
ReplyDeleteServo myservo ;
Servo myservo1 ;
void setup() {
myservo.attach(9);
myservo1.attach(10);
}
void p()
{
myservo.write(25);
myservo1.write(5);
}
void st()
{
myservo.write(150);
myservo1.write(65);
}
void sc()
{
myservo.write(25);
myservo1.write(75);
}
void loop(){
}
請問要加上什麼程式碼才能隨機執行這三個迴圈呢?
Deleteswitch(random(1,3)){
Deletecase 1:
p();
break;
case 2:
st();
break;
case 3:
sc();
break;
}
大概如此吧。
感謝,我試試看
Delete他只會跳到st耶
Delete為什麼會這樣?
改成random(1,4)
Delete#include
DeleteServo myservo ;
Servo myservo1 ;
Servo myservo2 ;
Servo myservo3 ;
Servo myservo4 ;
void setup() {
myservo.attach(9); // 食指 9
myservo1.attach(10); // 大拇指 10
myservo2.attach(11); // 中指 11
myservo3.attach(6); // 無名指 6
myservo4.attach(5); // 小拇指 5
}
void p()
{
myservo.write(25);
myservo1.write(5);
myservo2.write(40);
myservo3.write(20);
myservo4.write(15);
delay(200);
}
void st()
{
myservo.write(150);
myservo1.write(65);
myservo2.write(155);
myservo3.write(160);
myservo4.write(80);
delay(200);
}
void sc()
{
myservo.write(25);
myservo1.write(75);
myservo2.write(40);
myservo3.write(160);
myservo4.write(90);
delay(200);
}
void loop(){
switch(random(1,3)){
case 1:
p();
break;
case 2:
st();
break;
case 3:
sc();
break;
}
}
這是我完整的程式碼
Delete改成random(1,4)
Delete您好,我們想要用手機利用wifi控制門鎖
ReplyDelete網路都連得上,但還是沒反應
想請問是哪裡出了問題? 謝謝!
哪裡沒反應?
Delete再說清楚一點,執行的流程為何,看到什麼訊息。
序列阜監控裡面會跑出
DeleteContacting ESP8266...
Got response from ESP8266.
Connecting to wifi...
Wifi connected.
Setting up server...
Server ready.
然後我們用app inventer做門鎖開關
結果沒辦法控制
http://imgur.com/nr6WTAj 這是我們app inventer的樣子
程式在下面 謝謝~!
Delete你這程式是怎麼來的?
Delete裏頭的WiFiServer與WiFiClient,這是用來控制Arduino WiFi Shield (https://www.arduino.cc/en/Main/ArduinoWiFiShield) 的吧,可是你又用SoftwareSerial控制ESP8266,兩者不一樣啊。
我看到你以at指令控制ESP8266、連上網,然後就不管它了。
WiFiServer的部分,並沒有連接網路,自然就不會執行到if (client) {裡面去了。
我們是初學者,我們為了專題想要做出用APP可以開電子鎖
Delete這些程式是從網路上合併下來的
我們現在遇到了瓶頸,不知道程式哪部分需要改進
你是用ESP8266,可繼續用at指令跟它溝通,命令它建立server,接受client的連線。
Delete加油吧。
#include
ReplyDelete#include
#include
bool debugMode = true;
int lControl = 13;
const String SSID="kuo";
const String PASSWORD="19960624";
int keyIndex = 0;
int status = WL_IDLE_STATUS;
WiFiServer server(80);
bool wifiAndServerReady = false;
String logText = "";
SoftwareSerial ESP8266(4,5);
void setup() {
Serial.begin(9600);
ESP8266.begin(9600);
ESP8266.setTimeout(2000);
}
void loop() {
delay(1000);
if(wifiAndServerReady){
String line=readLine();
if(line!=""){
log("ESP8266: "+line);
}
proxyToESP8266();
}else{
if(!connectToWifi()){
log("Retry in 2 seconds...");
delay(2000);
}
}
WiFiClient client = server.available();
if (client) {
String currentLine = "";
while (client.connected()) {
if (client.available()) {
char c = client.read();
if(c == '\n') {
if (currentLine.length() == 0) {
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
client.print("Value at A0 is ");
client.print(analogRead(A0));
client.print("\n"); //
client.println();
break;
}
else {
currentLine = "";
}
}
else if (c != '\n'){ //'\r'
currentLine += c;
}
if (currentLine.endsWith("GET /H")) {
digitalWrite(lControl, HIGH);
}
if (currentLine.endsWith("GET /L")) {
digitalWrite(lControl, LOW);
}
}
}
client.stop();
}
}
bool waitForResponse(int timeout,String keyword1,String keyword2=""){
bool found = false;
while(true){
String response = readLine();
found = findKeyword(response,keyword1) || findKeyword(response,keyword2);
if(found || timeout<=0){
break;
}else{
delay(10);
timeout-=10;
if(response!=""){
timeout+=100;
}
}
}
return found;
}
bool connectToWifi(){
wifiAndServerReady=false;
log("Contacting ESP8266...");
sendCmd("AT");
if(waitForResponse(1000,"OK\r\n")){
log("Got response from ESP8266.");
log("Connecting to wifi...");
sendCmd("AT+CWJAP=\""+SSID+"\",\""+PASSWORD+"\"");
if(waitForResponse(3000,"OK\r\n")){
log("Wifi connected.");
log("Setting up server...");
sendCmd("AT+CWMODE=3\r\n"); // configure as STA+AP
sendCmd("AT+CIFSR\r\n"); // get ip address
sendCmd("AT+CIPMUX=1");
waitForResponse(1000,"OK\r\n");
sendCmd("AT+CIPSERVER=1,80");
if(waitForResponse(3000,"OK\r\n","no change\r\n")){
log("Server ready.");
wifiAndServerReady=true;
}else{
log("ERROR: Failed to set up server.");
}
}else{
log("ERROR: Failed to connect to Wifi.");
}
}else{
log("ERROR: Failed to contact ESP8266.");
}
return wifiAndServerReady;
}
void sendCmd(String cmdString){
cmdString=cmdString+"\r\n";
ESP8266.print(cmdString);
ESP8266.flush();
}
void proxyToESP8266(){
while (Serial.available()) {
int inByte = Serial.read();
ESP8266.write(inByte);
}
}
void log(String msg){
logText=logText+msg+"\n";
if(debugMode){
Serial.println(msg);
}
}
void printLog(){
Serial.print(logText);
}
bool findKeyword(String text,String keyword){
if(keyword==""){
return false;
}
return text.lastIndexOf(keyword)>-1;
}
String readLine(){
String lineString="";
while(ESP8266.available()){
char inChar = ESP8266.read();
lineString=lineString+String(inChar);
if(inChar=='\n'){
break;
}
}
return lineString;
}
請問電阻
ReplyDelete