Բովանդակություն:

Մենյու Arduino- ում և ինչպես օգտագործել կոճակները. 10 քայլ (նկարներով)
Մենյու Arduino- ում և ինչպես օգտագործել կոճակները. 10 քայլ (նկարներով)

Video: Մենյու Arduino- ում և ինչպես օգտագործել կոճակները. 10 քայլ (նկարներով)

Video: Մենյու Arduino- ում և ինչպես օգտագործել կոճակները. 10 քայլ (նկարներով)
Video: 1. Q Light Controller + Սկսել QLC +- ով: Արշավներ եւ գործառույթներ 2024, Նոյեմբեր
Anonim
Մենյու Arduino- ում և ինչպես օգտագործել կոճակները
Մենյու Arduino- ում և ինչպես օգտագործել կոճակները

Իմ Arduino 101 ձեռնարկում ձեզ կսովորեցնեն, թե ինչպես ստեղծել ձեր միջավայրը Tinkercad- ում: Ես օգտագործում եմ Tinkercad- ը, քանի որ այն բավականին հզոր առցանց հարթակ է, որն ինձ թույլ է տալիս մի շարք հմտություններ ցուցադրել ուսանողներին `սխեմաներ կառուցելու համար: Ազատորեն կառուցեք իմ բոլոր ձեռնարկները ՝ օգտագործելով Arduino IDE- ն և իսկական Arduino- ն:

Այս ձեռնարկում մենք կսովորենք կոճակների մասին: Մենք պետք է իմանանք.

  • Ինչպես դրանք լարել
  • Կարդալով դրանց արժեքը
  • Դեբունսիա, և ինչու է դա կարևոր
  • Գործնական ծրագիր (ընտրացանկի ստեղծում)

Մարդկանց մեծամասնությունը կարծում է, որ կոճակի հետ գործնականում անհրաժեշտ է միացնել և անջատել լույսը: Մենք կանենք, ոչ թե այստեղ: Մենք մերը կօգտագործենք `ընտրացանկ ստեղծելու և Arduino- ում որոշ տարբերակներ սահմանելու համար:

Պատրա՞ստ Եկեք սկսենք!

Քայլ 1: Ստեղծեք խորհուրդը

Կարգավորել խորհուրդը
Կարգավորել խորհուրդը
Կարգավորել խորհուրդը
Կարգավորել խորհուրդը

Առաջին քայլն այն է, որ Arduino- ն և Breadboard Small- ը տեղադրեն նախատիպավորման տարածք: Ստուգեք վերևի պատկերները ՝ տեսնելու, թե ինչպես միացնել էլեկտրական ռելսերը:

Breadboard Mini- ն ունի երկու հոսանքի ռելսեր ՝ վերևից և ներքևից: Մենք դրանք կապում ենք Arduino- ի հետ, որպեսզի կարողանանք էներգիա ապահովել ավելի շատ բաղադրիչների: Հետագայում այս ձեռնարկում մենք կօգտագործենք 3 կոճակ, այնպես որ մեզ ավելի շատ ուժ կպահանջվի: Պետք է նշել, որ փոքր տախտակի վրա հոսանքի ռելսերը անցնում են տախտակով ՝ հորիզոնական: Սա տարբերվում է մեջտեղում գտնվող հիմնական նախատիպերի տարածքի սյուներից: սրանք ուղղահայաց են աշխատում: Դուք կարող եք օգտագործել հոսանքի ցանկացած կապիչ ՝ մեջտեղում գտնվող հիմնական հատվածի ցանկացած սյունակ ապահովելու համար:

Երբ էներգիա եք ավելացնում, օգտագործեք սև և կարմիր լարերը համապատասխանաբար բացասականին և դրականին: Վերջում ավելացրեք լարեր, որոնք հոսանքը հոսում են տախտակի մյուս կողմում: Մենք չենք օգտագործի այդ կողմը, բայց դա լավ պրակտիկա է:

Քայլ 2: Ավելացրեք կոճակը և դիմադրությունը

Ավելացրեք կոճակը և դիմադրությունը
Ավելացրեք կոճակը և դիմադրությունը
Ավելացրեք կոճակը և դիմադրությունը
Ավելացրեք կոճակը և դիմադրությունը
Ավելացրեք կոճակը և դիմադրությունը
Ավելացրեք կոճակը և դիմադրությունը

Ավելացրեք մի փոքր կոճակ բաղադրիչների սկուտեղից: Այն պետք է նման լինի պատկերին: Համոզվեք, որ դա անջատիչ չէ: Ավելացրեք նաև դիմադրություն: Կտտացրեք այն և դրա արժեքը սահմանեք 10kΩ: Դա բավական է, որ քորոցը ցածր լինի, երբ այն միացված չէ, ինչը շատ կարևոր է հետագայում կոդի մեջ:

Տեղադրեք բաղադրիչը հացահատիկի կեսին: Կոճակի աշխատանքի եղանակը հետևյալն է.

  • Անկյուն անկյունից, կոճակը միացված չէ: Կոճակը սեղմելը փակում է կոնտակտները և միացնում անկյունները:
  • Կոճակի կողմերը միացված են: Եթե մետաղալար միացնեիք վերևի ձախ և ներքևի ձախ կողմերին, ապա միացումը կփակվեր:

Ահա թե ինչու մենք բաղադրիչը դնում ենք տարածության մեջտեղում: Այն համոզված է, որ անկյունները միացված չեն տախտակի քորոցների տակ:

Հաջորդ քայլը տալիս է մի քանի պատկեր, որոնք պատկերում են այս կետերը:

Տեղադրեք դիմադրությունը ներքևի աջ քորոցից սյուների վրայով, այնպես որ այն հորիզոնական նստած է:

Քայլ 3: Կոճակների միացումներ

Կոճակի միացումներ
Կոճակի միացումներ
Կոճակի միացումներ
Կոճակի միացումներ

Վերոնշյալ պատկերները բավականին պարզ են դարձնում, թե ինչպես են կոճակները միանում: Միշտ շփոթմունք էր, երբ կարծում ես, որ ինչ -որ բան ամեն ինչ լավ է, և այն չի աշխատում:

Հիմա եկեք ավելացնենք լարերը:

  • Տեղադրեք կարմիր հոսանք ՝ դրական հզորության քորոցից դեպի նույն սյունակ, ինչպես ներքևի աջ քորոցը կոճակի վրա
  • Տեղադրեք սև կապարը բացասական հզորության քորոցից դեպի նույն սյունակը, ինչ ռեզիստորը:
  • Տեղադրեք գունավոր մետաղալար (ոչ կարմիր/սև) վերևի ձախ քորոցից մինչև թվային կապ 2 Arduino- ի վրա

Ստուգեք վերը նշված պատկերները `համոզվելու համար, որ ձեր էլեկտրագծերը ճիշտ են:

Քայլ 4: Օրենսգիրքը…

Օրենսգիրքը…
Օրենսգիրքը…
Օրենսգիրքը…
Օրենսգիրքը…

Եկեք նայենք հիմնական կոճակի ծածկագրին:

Բացեք կոդի խմբագիրը և բլոկներից փոխեք տեքստի: Մաքրել նախազգուշացումը, որը գալիս է: Մենք գոհ ենք տեքստից:

Դուք գիտեք հիմնական կարգավորումը, ուստի եկեք սահմանենք կոճակը և կատարենք հիմնական ընթերցում: Մենք արդյունքը տպելու ենք Serial:

Ստորև բերված ծածկագրի մեջ ես մի քանի լրացուցիչ մեկնաբանություն եմ դնում, որպեսզի ավելի հեշտ լինի կարդալ, քան պատկերը:

// Սահմանել հաստատունները

#սահմանել կոճակը 2 void setup () {pinMode (կոճակ, Մուտք); Serial.begin (9600); } void loop () {// Կարդացեք թվային քորոցը ՝ ստուգելու կոճակի կարգավիճակը int pressed = digitalRead (կոճակ); // Կոճակը սեղմված է վերադառնում, եթե սեղմված է, OWԱOWՐ, եթե ոչ (սեղմված է == HIGH) {Serial.println ("Սեղմված է"); }}

Լավ, լավ է աշխատում:

Ըստ էության, այն ամենը, ինչ մենք անում ենք, ստուգում է թվային կապի կարգավիճակը ամեն անգամ, երբ ծածկագիրը շրջվում է: Եթե սեղմեք Start Simulation- ը և սեղմեք կոճակը, կտեսնեք Serial Monitor (կտտացրեք կոդի ներքևի կոճակին) «Սեղմված»: բազմիցս:

Մեկ հատկանիշ, որը դուք կտեսնեք վերը նշված ծածկագրում, տեղի է ունենում if () վիճակի գնահատում: Այն ամենը, ինչ անում է օրենսգիրքը, հարց տալն ու գնահատելն է, եթե այն ճշմարիտ է, այս դեպքում: Մենք օգտագործում ենք հավասար (հավասար կրկնակի նշաններ, օրինակ ՝ ==) ՝ ստուգելու համար, թե արդյոք փոփոխականի արժեքը հավասար է որոշակի արժեքի: DigitalRead () - ը վերադարձնում է կամ HIGH կամ LOW:

Եթե () այլ դեպքում, եթե / այլ կերպ մենք կարող ենք ստուգել բազմաթիվ պայմաններ կամ բոլոր պայմանները, և եթե վերադառնաք Arduino հիմունքներին, կտեսնեք որոշ համեմատություններ, որոնք կարող եք կատարել:

Հիմա… Մեր ծածկագիրը կարող է ամբողջական տեսք ունենալ … Բայց մենք խնդիր ունենք:

Տեսեք, դա իսկապես լավ է աշխատում, երբ սիմուլյատորում է: Բայց իրական էլեկտրաէներգիան աղմուկ ունի, հատկապես DC էլեկտրոնիկան: Այսպիսով, մեր կոճակը երբեմն կարող է վերադարձնել կեղծ ընթերցում: Եվ դա խնդիր է, քանի որ ձեր նախագիծը կարող է ճիշտ չարձագանքել օգտվողին:

Եկեք շտկենք:

Քայլ 5: Մի փոքր հերքում

Մի փոքր դեբունզ
Մի փոքր դեբունզ

Մենք օգտագործում ենք ընթացակարգ, որը կոչվում է դեբունս `կոճակի մեր խնդիրը հաղթահարելու համար: Սա, ըստ էության, սպասում է որոշակի ժամանակ կոճակը սեղմելուց և իրականում արձագանքելուն հրումին: Այն դեռ բնական է թվում օգտագործողի համար (եթե ժամանակը շատ երկար չդարձնեք): Կարող եք օգտագործել նաև մամուլի երկարությունը ստուգելու համար, այնպես որ ամեն անգամ կարող եք այլ կերպ արձագանքել: Անհրաժեշտ չէ փոխել էլեկտրագծերը:

Եկեք նայենք ծածկագրին.

#սահմանել կոճակը 2#սահմանել debounceTimeout 100 -ը

Առաջին փոփոխությունը վերաբերում է գլոբալ շրջանակին: Դուք կհիշեք, որ այնտեղ մենք սահմանում ենք փոփոխականներ, որոնք կարող են օգտագործել մեր գործառույթներից շատերը կամ այն գործառույթները, որոնք հնարավոր չէ վերականգնել ամեն անգամ, երբ օղակը գործարկվի: Այսպիսով, մենք ավելացրեցինք debounceTimeout- ը սահմանված հաստատուններին: Մենք պատրաստեցինք այս 100 -ը (որը հետագայում կթարգմանվի 100 մ), բայց կարող է ավելի կարճ լինել: Այլևս, և դա անբնական կզգա:

long int lastDebounceTime;

Այս փոփոխականը հայտարարվում է հաստատուններից ցածր: Սա երկար int տեսակ է, որը հիմնականում թույլ է տալիս մեզ երկար թվեր պահել հիշողության մեջ: Մենք այն անվանում էինք lastDebounceTime:

Մենք կարիք չունենք որևէ բան փոխելու void setup () գործառույթում: Թողնենք այդ մեկը:

void loop () {// Կարդացեք թվային քորոցը ՝ ստուգելու կոճակի կարգավիճակը int pressed = digitalRead (կոճակ); long int currentTime = millis (); // կոճակի կոդ}

Առաջին փոփոխությունը, որը մենք կատարում ենք loop () գործառույթում, գտնվում է կոճակը կարդալու կոչի ներքո: Մենք պետք է հետևենք ընթացիկ ժամանակին: Millis () գործառույթը վերադարձնում է ժամացույցի ընթացիկ ժամանակը, քանի որ Arduino- ն միացել է միլիվայրկյանում: Մենք պետք է սա պահենք երկար int տիպի փոփոխականի մեջ:

Այժմ, մենք պետք է համոզվենք, որ մենք տեղյակ ենք կոճակը սեղմվելուց հետո եղած ժամանակի մասին, այնպես որ մենք վերականգնում ենք ժմչփը, երբ այն սեղմված չէ: Նայել:

void loop () {// Կարդացեք թվային քորոցը ՝ ստուգելու կոճակի կարգավիճակը int pressed = digitalRead (կոճակ); long int currentTime = millis (); եթե (սեղմված == LOW) {// Վերականգնել հաշվման ժամանակը, մինչ կոճակը սեղմված չէ lastDebounceTime = currentTime; } // կոճակի կոդ}

Եթե (սեղմված == OWԱOWՐ) ալգորիթմը ստուգում է, արդյոք կոճակը սեղմված չէ: Եթե դա այդպես չէ, ապա կոդը պահում է ընթացիկ ժամանակը վերջին դեբունսից հետո: Այդ կերպ, ամեն անգամ, երբ կոճակը սեղմվում է, մենք ունենում ենք ժամանակի մի պահ, որից կարող ենք ստուգել, երբ կոճակը սեղմվել է: Այնուհետև մենք կարող ենք արագ մաթեմատիկական հաշվարկ կատարել ՝ տեսնելու համար, թե որքան ժամանակ է սեղմվել կոճակը և ճիշտ արձագանքել: Եկեք նայենք մնացած ծածկագրին.

void loop () {// Կարդացեք թվային քորոցը ՝ ստուգելու կոճակի կարգավիճակը int pressed = digitalRead (կոճակ); long int currentTime = millis (); եթե (սեղմված == LOW) {// Վերականգնել հաշվման ժամանակը, մինչ կոճակը սեղմված չէ lastDebounceTime = currentTime; } // Կոճակը սեղմված է որոշակի ժամանակ, եթե ((((currentTime - lastDebounceTime)> debounceTimeout)) {// Եթե ժամկետը լրացել է, սեղմել կոճակը: Serial.println («Սեղմված է»); }}

Կոդի վերջին բլոկը վերցնում է ընթացիկ ժամանակը, հանում է վերջին դուրսբերման ժամանակը և համեմատում այն մեր սահմանած ժամանակի հետ: Եթե այն ավելի մեծ է, կոդը ենթադրում է, որ կոճակը սեղմված է այդ ժամանակ և արձագանքում է: Կոկիկ!

Գործարկեք ձեր կոդը և ստուգեք, որ այն աշխատում է: Եթե սխալներ ունեք, ստուգեք ձեր ծածկագիրը:

Այժմ, եկեք նայենք գործնական օրինակին:

Քայլ 6: Մենյուի պատրաստում

Menաշացանկի պատրաստում
Menաշացանկի պատրաստում

Կոճակները հետաքրքիր են, քանի որ դրանց հետ շատ հնարավորություններ կան: Այս օրինակում մենք պատրաստելու ենք մենյու: Ենթադրենք, դուք ստեղծել եք այս հիանալի սարքը և կարիք ունեք, որ օգտվողները կարողանան փոխել տարբերակները ՝ որոշակի իրեր միացնելու կամ անջատելու համար կամ որոշակի արժեք սահմանելու համար: Այս երեք կոճակների դիզայնը կարող է դա անել:

Այսպիսով, այս նախագծի համար մեզ անհրաժեշտ է.

  • Երեք կոճակ
  • Երեք ռեզիստոր `10kΩ- ի սահմանաչափով

Մենք արդեն ունենք դրանցից մեկը, մեզ պարզապես անհրաժեշտ է մյուս երկուսը: Այսպիսով, դրանք ավելացրեք գրատախտակին: Միացումը մի փոքր ավելի բարդ է, բայց միայն այն պատճառով, որ ես ուզում էի այն իսկապես կոմպակտ պահել: Կարող եք հետևել նույն օրինակին առաջին կոճակի համար կամ հետևել վերևի պատկերին:

Երեք կոճակներն են `ընտրացանկի բաց/հաջորդ տարբերակ, փոփոխման տարբերակ (ինչպես պարագայում, փոփոխել կարգավորումը) և ընտրացանկի պահպանման/փակման կոճակը:

Լարեք այն, եկեք նայենք ծածկագրին:

Քայլ 7. Կոդի խզում - Գլոբալ

Լավ, սա երկար քայլ կլինի, բայց ես պատրաստվում եմ անցնել կոդի յուրաքանչյուր հատված:

Նախ, եկեք նայենք անհրաժեշտ գլոբալ փոփոխականներին:

// Սահմանել հաստատունները #սահմանել ընտրացանկը Կոճակ 2 #սահմանել ընտրացանկըԸնտրել 3 #սահմանել ընտրացանկըԽնայել 4 #սահմանել դեբունս imeամկետը 50 // սահմանել փոփոխականներ int menuButtonPreviousState = LOW; int menuSelectPreviousState = OWԱOWՐ; int menuSavePreviousState = OWԱOWՐ; long int lastDebounceTime; // uանկի ընտրանքներ char * menuOptions = {"Ստուգեք ջերմաստիճանը", "Ստուգեք լույսը"}; bool featureSetting = {կեղծ, կեղծ}; bool menuMode = false; bool menuNeedsPrint = կեղծ; int տարբերակ Ընտրված է = 0;

Այս երեք բլոկները բավականին նման են նրան, ինչ մենք նախկինում տեսել էինք: Առաջինում ես սահմանել եմ երեք կոճակները և ժամանակի ավարտը: Partրագրի այս մասի համար ես այն սահմանել եմ 50ms, այնպես որ այն աշխատելու համար դիտավորյալ մամուլ է պահանջվում:

Երկրորդ բլոկը բոլոր փոփոխականներն են: Մենք պետք է հետևենք buttonPreviousState- ին, և մենք պետք է հետևենք վերջինDebounceTime- ին: Սրանք բոլորը int տիպի փոփոխականներ են, բայց վերջինը երկար տիպ է, քանի որ ես ենթադրում եմ, որ մեզ անհրաժեշտ է տարածություն հիշողության մեջ:

Theաշացանկի ընտրանքների բլոկն ունի մի քանի նոր գործառույթ: Նախ, նշանը * (այո, դա դիտավորյալ աստղանիշ է), որը բնույթի/տողի բառացի փոփոխական է: Այն ցուցիչ է հիշողության մեջ ստատիկ պահեստավորման համար: Դուք չեք կարող փոխել այն (ինչպես կարող եք, օրինակ, Python- ում): Այս char *menuOptions տողը ստեղծում է լարային բառացի զանգված: Կարող եք ավելացնել ցանկի այնքան տարր, որքան ցանկանում եք:

Bool featureSetting փոփոխականն ընդամենը այն արժեքների զանգվածն է, որը ներկայացնում է ընտրացանկի յուրաքանչյուր տարր: Այո, դուք կարող եք պահել այն, ինչ ձեզ դուր է գալիս, պարզապես փոխել փոփոխականի տեսակը (դրանք բոլորը պետք է լինեն նույն տեսակը): Այժմ, հնարավոր է, որ դա կառավարելու ավելի լավ եղանակներ լինեն, ինչպես բառարանները կամ բազմապատիկները, բայց սա պարզ է այս հավելվածի համար: Ես, հավանաբար, վերջիններից մեկը կստեղծեի տեղակայված հավելվածում:

Ես հետևել եմ menuMode- ին, այնպես որ, եթե ցանկանայի այլ բաներ ցուցադրելիս, կարող էի դա անել: Բացի այդ, եթե ես ունեի սենսորային տրամաբանություն, ես կարող էի դա դադարեցնել մենյուի աշխատանքի ընթացքում, միայն այն դեպքում, եթե ինչ -որ բան հակասում էր: Ես ունեմ menuNeedsPrint փոփոխական, որովհետև ուզում եմ ընտրացանկը տպել որոշակի ժամանակներում, ոչ միայն անընդհատ: Ի վերջո, ես ունեմ optionSelected փոփոխական, այնպես որ կարող եմ հետևել ընտրված տարբերակին, քանի որ այն մուտք եմ գործում մի շարք վայրերում:

Եկեք նայենք գործառույթների հաջորդ փաթեթին:

Քայլ 8. Կոդի խափանում - կարգավորում և հարմարեցված գործառույթներ

Setup () գործառույթը բավականին հեշտ է, ընդամենը երեք մուտքային հայտարարություն.

void setup () {pinMode (menuSelect, INPUT); pinMode (menuSave, INPUT); pinMode (ընտրացանկ, Ընտրություն, Մուտք); Serial.begin (9600); }

Հաջորդը երեք սովորական գործառույթներն են: Եկեք անդրադառնանք առաջին երկուսին, ապա վերջինին առանձին:

Մեզ անհրաժեշտ են երկու գործառույթներ, որոնք վերադարձնում են որոշ տեղեկություններ: Պատճառն այն է, որ մենք ցանկանում ենք համոզվել, որ սա ինչ -որ կերպ մարդկային ընթեռնելի է: Այն նաև կօգնի կոդի շտկման հարցում, եթե խնդիր ունենանք: Կոդ:

// Ընթացիկ ընտրված տարբերակի վերադարձման գործառույթը *ReturnOptionSelected () {char *menuOption = menuOptions [optionSelected]; // Return optionSelected return menuOption; } // Ընթացիկ ընտրված տարբերակի կարգավիճակը վերադարձնելու գործառույթ char *ReturnOptionStatus () {bool optionSetting = featureSetting [optionSelected]; char *optionSettingVal; եթե (optionSetting == false) {optionSettingVal = "Կեղծ"; } else {optionSettingVal = "Trueշմարիտ"; } // Return optionSetting return optionSettingVal; }

Char *ReturnOptionSelected () գործառույթը ստուգում է ընտրված տարբերակը (եթե վերևում տեսնում եք, մենք փոփոխական ենք սահմանում դա հետևելու համար) և տողը բառացիորեն հանում է ավելի վաղ ստեղծված զանգվածից: Այնուհետեւ այն վերադարձնում է որպես ածխածնի տեսակ: Մենք դա գիտենք, քանի որ գործառույթը ցույց է տալիս վերադարձի տեսակը:

Երկրորդ գործառույթը ՝ char *ReturnOptionStatus () կարդում է զանգվածում պահված տարբերակի կարգավիճակը և վերադարձնում տող բառացի, որը ներկայացնում է արժեքը: Օրինակ, եթե մեր պահած կարգավորումը կեղծ է, ես կվերադառնայի «Կեղծ»: Դա պայմանավորված է նրանով, որ մենք օգտվողին ցույց ենք տալիս այս փոփոխականը, և ավելի լավ է այս ամբողջ տրամաբանությունը միասին պահել: Ես կարող էի դա անել ավելի ուշ, բայց ավելի իմաստալից է դա անել այստեղ:

// Ընթացիկ ընտրանքն անջատելու գործառույթ Tool/ OptionSelected () {featureSetting [optionSelected] =! FeatureSetting [optionSelected]; վերադարձնել ճշմարիտ; }

Bool գործառույթը ToggleOptionSelected () հարմարության գործառույթ է ՝ ընտրացանկում մեր ընտրած պարամետրի արժեքը փոխելու համար: Դա պարզապես շրջում է արժեքը: Եթե դուք ունեիք ընտրանքների ավելի բարդ շարք, սա կարող է բոլորովին այլ լինել: Այս գործառույթում ես վերադարձնում եմ ճշմարիտ, քանի որ իմ հետադարձ կապը (հետագայում այս գործառույթը գործարկող կոդի զանգը) ակնկալում է ճշմարիտ/կեղծ պատասխան: Ես 100% վստահ եմ, որ դա կաշխատի, այնպես որ ես հաշվի չէի առնում, որ այն չի աշխատում, բայց ես դա կիրառում եմ տեղակայված ծրագրում (ամեն դեպքում):

Քայլ 9: Օղակը…

Loop () գործառույթը բավականին երկար է, ուստի մենք դա կանենք մաս -մաս: Այս գործառույթի շրջանակներում կարող եք ենթադրել, որ ներքևում գտնվող ամեն ինչ:

դատարկ շրջան () {

// Աշխատիր այստեղ <-----}

Լավ, մենք նախկինում տեսել էինք այս իրերը.

// Կարդալ կոճակները int menuButtonPressed = digitalRead (menuButton); int menuSelectPressed = digitalRead (menuSelect); int menuSavePressed = digitalRead (menuSave); // Ստացեք ընթացիկ ժամանակը երկար int currentTime = millis (); if (menuButtonPressed == LOW && menuSelectPressed == LOW && menuSavePressed == LOW) {// Վերականգնել հաշվարկի ժամանակը, մինչ կոճակը սեղմված չէ lastDebounceTime = currentTime; menuButtonPreviousState = OWԱOWՐ; menuSelectPreviousState = OWԱOWՐ; menuSavePreviousState = OWԱOWՐ; }

Այստեղ ինձ մնում էր ավելացնել digitalRead () երեք զանգերը և համոզվել, որ հաշվի եմ առել այն փաստը, որ եթե բոլոր կոճակները ցածր էին, մենք պետք է զրոյականացնենք ժամանակաչափը (lastDebounceTime = currentTime) և բոլոր նախորդ վիճակները դնենք ցածր: Ես նաև millis () եմ պահում ընթացիկ ժամանակում:

Հաջորդ հատվածը բնադրում է գծի ներսում

if (((currentTime - lastDebounceTime)> debounceTimeout)) {

// Աշխատիր այստեղ <----}

Երեք բաժին կա: Այո, ես կարող էի դրանք տեղափոխել իրենց գործառույթների մեջ, բայց պարզության համար ես այստեղ պահեցի կոճակի երեք հիմնական ալգորիթմը:

if ((menuButtonPressed == HIGH) && (menuButtonPreviousState == LOW)) {if (menuMode == false) {menuMode = true; // Օգտվողին տեղեկացրեք Serial.println («Մենյուը ակտիվ է»); } else if (menuMode == true && optionSelected = 1) {// Վերականգնել ընտրանքային ընտրանքըSelected = 0; } // Տպել ընտրացանկի menuNeedsPrint = true; // Փոխել կոճակը նախ. նշեք միայն ցանկի ցուցադրման // եթե կոճակը բաց է թողնվում և նորից սեղմվում menuButtonPreviousState = menuButtonPpress; // կլիներ ԲԱՐՁՐ}

Սա առաջինն է, երբ menuButtonPressed- ը բարձր է, կամ երբ ընտրացանկի կոճակը սեղմված է: Այն նաև ստուգում է ՝ համոզվելու համար, որ նախորդ վիճակը OWԱOWՐ է, այնպես որ կոճակը պետք է բաց թողնվի նախքան այն նորից սեղմելը, ինչը խանգարում է ծրագրին անընդհատ նույն իրադարձությունը կրակել անընդհատ:

Այնուհետև ստուգում է, որ եթե ընտրացանկը ակտիվ չէ, այն ակտիվացնում է: Այն տպելու է ընտրված առաջին տարբերակը (որը ընտրացանկի առաջին տարրն է լռելյայնորեն: Եթե երկրորդ կամ երրորդ (և այլն) անգամ սեղմեք կոճակը, ցուցակում կստանաք հաջորդ տարբերակը: Ինչ -որ բան, որը ես կարող էի շտկել, դա է որ երբ այն հասնի ավարտին, այն ցիկլով վերադառնում է դեպի սկիզբ: Սա կարող է կարդալ զանգվածի երկարությունը և հեշտացնել հեծանվավազքը, եթե փոխեք տարբերակների քանակը, բայց սա առայժմ պարզ էր:

Վերջին փոքր հատվածը (// Տպում է ընտրացանկը) ակնհայտորեն տպում է ընտրացանկը, բայց այն նաև սահմանում է նախորդ վիճակը HIGH- ի վրա, այնպես որ նույն գործառույթը չի շրջանցվում (տե՛ս վերևում իմ գրառումը ՝ կոճակը նախկինում OWԱOWՐ լինելու մասին):

// menuSelect- ը սեղմված է, տրամադրեք logicif ((menuSelectPressed == HIGH) && (menuSelectPreviousState == LOW)) {if (menuMode) {// Փոխել ընտրված տարբերակը // Այս պահին սա պարզապես ճիշտ է/կեղծ // բայց could be something bool toggle = ToggleOptionSelected (); if (միացնել) {menuNeedsPrint = true; } else {Serial.println ("Սխալ առաջացավ. Խնդրում ենք կրկին փորձել"); }} // Միացնել / անջատել միայն բաց թողնելու դեպքում և նորից սեղմել menuSelectPreviousState = menuSelectPressed; }

Այս կոդի մի մասը նույն կերպ վարում է menuSelectPressed կոճակը, բացառությամբ այս անգամ մենք պարզապես միացնում ենք ToggleOptionSelected () գործառույթը: Ինչպես արդեն ասացի, դուք կարող եք փոխել այս գործառույթը, որպեսզի այն ավելին անի, բայց դա այն ամենն է, ինչ ինձ պետք է:

Հիմնական բանը, որ պետք է նշել, միացման փոփոխականն է, որը հետևում է հետադարձ կապի հաջողությանը և, եթե այն ճշմարիտ է, տպում է ընտրացանկը: Եթե այն ոչինչ կամ կեղծ չի վերադարձնում, այն տպելու է սխալի հաղորդագրությունը: Սա այն վայրն է, որտեղ դուք կարող եք օգտագործել ձեր հետադարձ կապը այլ բաներ անելու համար:

if ((menuSavePressed == HIGH) && (menuSavePreviousState == LOW)) {// Դուրս եկեք ընտրացանկից // Այստեղ կարող եք ցանկացած կարգի բերել // կամ պահել EEPROM menuMode = false; Serial.println («Մենյուից դուրս եկավ»); // Անջատել վիճակը, այնպես որ մենյուն դուրս է գալիս միայն մեկ անգամ menuSavePreviousState = menuSavePressed; }}

Այս գործառույթը կարգավորում է menuSave կոճակը, որը պարզապես դուրս է գալիս ընտրացանկից: Սա այն վայրն է, որտեղ դուք կարող եք չեղյալ հայտարարել կամ պահպանել տարբերակ, գուցե ինչ -որ մաքրում կատարել կամ պահել EEPROM- ում: Ես պարզապես տպում եմ «Menu outed» - ը և կոճակի վիճակը դնում եմ HIGH- ի վրա, որպեսզի այն չշրջվի:

եթե (menuMode && menuNeedsPrint) {// Մենք տպել ենք ընտրացանկը, այնպես որ, եթե ինչ -որ բան տեղի չունենա, կարիք չկա նորից տպել menuNeedsPrint = false; char *optionActive = ReturnOptionSelected (); char *optionStatus = ReturnOptionStatus (); Serial.print ("Ընտրված է"); Serial.print (optionActive); Serial.print (":"); Serial.print (optionStatus); Serial.println (); }

Սա menuPrint ալգորիթմն է, որն աշխատում է միայն այն ժամանակ, երբ ընտրացանկը ակտիվ է, և երբ menuNeedsPrint փոփոխականը ճշմարիտ է:

Սա անպայման կարող էր տեղափոխվել իր գործառույթին, բայց հանուն պարզության..!

Դե, վերջ! Կոդի ամբողջ բլոկի համար տես հաջորդ քայլը:

Քայլ 10: Վերջնական ծածկագրի արգելափակում

// Սահմանել հաստատունները

#սահմանել ընտրացանկը Կոճակ 2 #սահմանել ընտրացանկը Ընտրել 3 #սահմանել ընտրացանկը Պահել 4 #սահմանել դեբունսը Timeout 50 int menuButtonPreviousState = LOW; int menuSelectPreviousState = OWԱOWՐ; int menuSavePreviousState = OWԱOWՐ; // Սահմանել փոփոխականներ int int lastDebounceTime; bool lightSensor = ճշմարիտ; bool tempSensor = ճշմարիտ; // uանկի ընտրանքներ char * menuOptions = {"Ստուգեք ջերմաստիճանը", "Ստուգեք լույսը"}; bool featureSetting = {կեղծ, կեղծ}; bool menuMode = false; bool menuNeedsPrint = կեղծ; int տարբերակ Ընտրված է = 0; // Կարգավորման գործառույթ

void setup () {pinMode (menuSelect, INPUT); pinMode (menuSave, INPUT); pinMode (ընտրացանկ, Ընտրություն, Մուտք); Serial.begin (9600); }

// Ընթացիկ ընտրված տարբերակը վերադարձնելու գործառույթը char *ReturnOptionSelected () {char *menuOption = menuOptions [optionSelected]; // Return optionSelected return menuOption; } // Ընթացիկ ընտրված տարբերակի կարգավիճակը վերադարձնելու գործառույթ char *ReturnOptionStatus () {bool optionSetting = featureSetting [optionSelected]; char *optionSettingVal; եթե (optionSetting == false) {optionSettingVal = "Կեղծ"; } else {optionSettingVal = "Trueշմարիտ"; } // Return optionSetting return optionSettingVal; } // Ընթացիկ ընտրանքն անջատելու գործառույթ bool ToggleOptionSelected () {featureSetting [optionSelected] =! FeatureSetting [optionSelected]; վերադարձնել ճշմարիտ; } // Հիմնական հանգույց

void loop () {// Կարդալ կոճակները int menuButtonPressed = digitalRead (menuButton); int menuSelectPressed = digitalRead (menuSelect); int menuSavePressed = digitalRead (menuSave); // Ստացեք ընթացիկ ժամանակը երկար int currentTime = millis (); if (menuButtonPressed == LOW && menuSelectPressed == LOW && menuSavePressed == LOW) {// Վերականգնել հաշվարկի ժամանակը, մինչ կոճակը սեղմված չէ lastDebounceTime = currentTime; menuButtonPreviousState = OWԱOWՐ; menuSelectPreviousState = OWԱOWՐ; menuSavePreviousState = OWԱOWՐ; } if (((currentTime - lastDebounceTime)> debounceTimeout)) {// Եթե ժամկետը լրացել է, սեղմեք կոճակը:

// menuButton- ը սեղմված է, տրամադրեք տրամաբանություն

// Կրակում է միայն այն ժամանակ, երբ կոճակը նախկինում ազատ է արձակվել, եթե ((menuButtonPressed == HIGH) && (menuButtonPreviousState == LOW)) {if (menuMode == false) {menuMode = true; // Օգտվողին տեղեկացրեք Serial.println («Մենյուը ակտիվ է»); } else if (menuMode == true && optionSelected = 1) {// Վերականգնել ընտրանքային ընտրանքըSelected = 0; } // Տպել ընտրացանկի menuNeedsPrint = true; // Փոխել կոճակը նախ. նշեք միայն ցանկի ցուցադրման // եթե կոճակը բաց է թողնվում և նորից սեղմվում menuButtonPreviousState = menuButtonPpress; // կլիներ HIGH} // menuSelect- ը սեղմված է, տրամադրեք տրամաբանություն, եթե ((menuSelectPressed == HIGH) && (menuSelectPreviousState == LOW)) {if (menuMode) {// Փոխել ընտրված տարբերակը // Այս պահին սա է պարզապես true/false // բայց կարող է լինել որևէ բան bool toggle = ToggleOptionSelected (); if (միացնել) {menuNeedsPrint = true; } else {Serial.print ("Սխալ առաջացավ. Խնդրում ենք կրկին փորձել"); }} // Միացնել / անջատել միայն բաց թողնելու դեպքում և նորից սեղմել menuSelectPreviousState = menuSelectPressed; } if ((menuSavePressed == HIGH) && (menuSavePreviousState == LOW)) {// Դուրս եկեք ընտրացանկից // Այստեղ կարող եք ցանկացած կարգի բերել // կամ պահել EEPROM menuMode = false; Serial.println («Մենյուից դուրս եկավ»); // Անջատել վիճակը, այնպես որ մենյուն դուրս է գալիս միայն մեկ անգամ menuSavePreviousState = menuSavePressed; }} // Տպել ընթացիկ ընտրացանկի տարբերակը ակտիվ, բայց տպել միայն մեկ անգամ, եթե (menuMode && menuNeedsPrint) {// Մենք տպել ենք ընտրացանկը, այնպես որ, եթե ինչ -որ բան տեղի չունենա, կարիք չկա նորից տպել menuNeedsPrint = false; char *optionActive = ReturnOptionSelected (); char *optionStatus = ReturnOptionStatus (); Serial.print ("Ընտրված է."); Serial.print (optionActive); Serial.print (":"); Serial.print (optionStatus); Serial.println (); }}}

Շղթան հասանելի է Tinkercad կայքում: Ես ներքևում միացրել եմ շրջանը, որպեսզի դուք նույնպես տեսնեք:

Ինչպես միշտ, եթե ունեք հարցեր կամ հարցեր, խնդրում եմ ինձ տեղյակ պահեք:

Խորհուրդ ենք տալիս: