Hemlig knackning upptäcka låda Lock(origional) (4 / 8 steg)
Steg 4: Steg 4: kod
Koden
Detta projekt använder enkel Arduino kod och Arduino EEPROM standardbiblioteket. Kopiera och klistra in koden nedan i en ny skiss och ladda upp den till din fasad.
Kopiera koden
/ * Hemliga slå prydnadssak kod för att köra en hemlighet slå lock på Adafruit prydnadssak. Version 13.10.31 byggt med Arduino IDE 1.0.5 By Steve Hoefer http://grathio.com licensierade under Creative Commons Erkännande-Ickekommersiell-Dela Lika 3.0 http://grathio.com (kort sagt: gör vad du vill, så länge du kreditera mig, inte omlicensiera det och inte sälja det eller använda det i något du säljer utan att kontakta mig.)---ledningar---Pin 0: post A nya Knock-knappen. Stift 1: (använder den inbyggda LED) Pin 2 (Analog 1): ett piezoelement för pipa och avkänning smällar. Stift 3: Ansluter till en transistor som öppnar en magnetventil låsa när HIGH.* / #include const byte eepromValid = 123. Om den första byten i eeprom är detta då är data giltiga. / * Pin-definitioner * / const int programButton = 0; Post A nya Knock button.const int ledPin = 1; Den inbyggda LEDconst int gaspedalsignal = 1; (Analog 1) för att använda piezo som en inmatningsenhet. (aka knock sensor) const int audioOut = 2; (Digitalkabel 2) för att använda peizo som en utdataenhet. (Sak som går beep.) CONST int lockPin = 3; PIN-koden som aktiverar magnetventilen låset. / * Tuning konstanter. Ändra värdena nedan ändrar uppförandet av tröskeln-enhet. * / int = 3; Minsta signal från piezo registreras som en knock. Högre = mindre känslig. Typiska värden 1 - 10const int rejectValue = 25; Om en enskild knock off av denna procentandel knackade vi inte låsa upp. Typiska värden 10-30const int averageRejectValue = 15. Om den genomsnittliga timingen av alla smällar är avstängd med denna procent vi inte låsa upp. Typiska värden 5-20const int knockFadeTime = 150; Millisekunder vi tillåta en knock blekna innan vi lyssnar efter en annan. (Debounce timer.) CONST int lockOperateTime = 2500; Millisekunder att vi verkar låsa nödsänkningssolenoiden spärren innan du släpper it.const int maximumKnocks = 20; Maximalt antal smällar lyssna for.const int knockComplete = 1200; Längsta tid att vänta på en knock innan vi antar att den är klar. (millisekunder) byte secretCode [maximumKnocks] = {50, 25, 25, 50, 100, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; Första installationen: "Rakning och en klippa, två bitar" int knockReadings [maximumKnocks]; När någon knackar här matrisen fyller med förseningarna mellan knocks.int knockSensorValue = 0; Sista behandlingen av knock sensor.boolean programModeActive = false; Sant om vi försöker programmera en ny knock. void setup() {pinMode (ledPin, produktionen), pinMode (lockPin, produktionen); readSecretKnock(); / / Ladda den Hemlig knackning (om någon) från EEPROM. doorUnlock(500); / / Lås upp dörren för lite när vi slår upp. För systemkontroll och att tillåta ett sätt i om är nyckeln glömd. Delay(500); Denna försening beror här magnetventil lås återvänder för att placera kan annars trigger och oavsiktlig knock.} void loop() {/ / lyssna för någon knock på alla. knockSensorValue = analogRead(knockSensor); om (digitalRead(programButton) == hög) {/ / trycks programknappen? Delay(100); Billiga debounce. om (digitalRead(programButton) == hög) {om (programModeActive == false) {/ / om vi inte i programmeringsläget, slå på den. programModeActive = true; / / kom ihåg vi är i programmering läge. digitalWrite (ledPin, hög); / / slå på rött ljus för så användaren vet vi är programmering. KVITTER (500, 1500); / / och spela en ton i fall användaren inte kan se den LED. KVITTER (500, 1000);} annat {/ / om vi är i programmering läge , stänga av den. programModeActive = false; digitalWrite (ledPin, låg); KVITTER (500, 1000); Stäng av den programmering LED och spela en sorglig notering. KVITTER (500, 1500); Delay(500); {} medan (digitalRead(programButton) == hög) {delay(10); / / hänga tills knappen släpps.}} Delay(250); En annan billig debounce. Längre eftersom släppa knappen kan ibland vara kände som en knock. } om (knockSensorValue > = tröskelvärde) {om (programModeActive == true) {/ / blinkar lysdioden när anar vi en knock. digitalWrite (ledPin, låg);} annat {digitalWrite (ledPin, hög);} knockDelay(); om (programModeActive == true) {/ / FN-blink LED. digitalWrite (ledPin, hög);} annat {digitalWrite (ledPin, låg);} listenToSecretKnock(); / / vi har vår första knock. Gå och se vad andra smällar i butik...} } / / Records tidpunkten för knocks.void listenToSecretKnock() {int jag = 0; / / först återställa den lyssnande array. för (jag = 0; jag < maximumKnocks; i ++) {knockReadings [i] = 0;} int currentKnockNumber = 0; / / läge counter för matris. int startTime = millis(); / / referens för när denna knock började. int nu = millis(); göra {/ / lyssna för den nästa knock eller vänta på att timeout. knockSensorValue = analogRead(knockSensor); om (knockSensorValue > = tröskelvärde) {/ / här är en annan knock. Spara tiden mellan smällar. Now=Millis(); knockReadings [currentKnockNumber] = nu - startTime; currentKnockNumber ++; startTime = nu; om (programModeActive == true) {/ / blinkar lysdioden när anar vi en knock. digitalWrite (ledPin, låg);} annat {digitalWrite (ledPin, hög);} knockDelay(); om (programModeActive == true) {/ / FN-blink LED. digitalWrite (ledPin, hög);} annat {digitalWrite (ledPin, låg);}} nu = millis(); Sluta lyssna om det finns alltför många smällar eller det finns för mycket tid mellan smällar. } medan ((nu-startTime < knockComplete) & & (currentKnockNumber < maximumKnocks)); Vi har fått våra knock registreras, kan se om det är giltigt om (programModeActive == false) {/ / endast göra detta om vi inte spelar in en ny knock. om (validateKnock() == true) {doorUnlock(lockOperateTime);} annat {/ / knock är ogiltig. Blinka lysdioden som en varning till andra. för (jag = 0; jag < 4; i ++) {digitalWrite (ledPin, hög); delay(50); digitalWrite (ledPin, låg); delay(50);}} {} annat {/ / om vi är i programmering läge vi fortfarande validera låsa eftersom det gör några siffror som vi behöver, vi bara inte göra någonting med den avkastning. validateKnock();}} Låser upp den door.void doorUnlock (int fördröjningstid) {digitalWrite (ledPin, hög), digitalWrite (lockPin, hög), delay(delayTime), digitalWrite (lockPin, låg), digitalWrite (ledPin, låg), delay(500); / / denna försening är här eftersom släpper spärren kan orsaka en vibration som kommer att vara kände som en knock.} / / kontrollerar om våra knock matchar secret.// Returnerar sant om det är en bra knock, falskt om det är not.boolean validateKnock() {int jag = 0; int currentKnockCount = 0; int secretKnockCount = 0; int maxKnockInterval = 0; / / vi använder detta senare för att normalisera gånger. för (jag = 0; i 0) {currentKnockCount ++;} om (secretCode [i] > 0) {secretKnockCount ++;} om (knockReadings [i] > maxKnockInterval) {/ / samla normalisering data medan vi looping. maxKnockInterval = knockReadings [i];}} Om vi spelar in en ny knock, spara info och få ut härifrån. om (programModeActive == true) {för (jag = 0; jag < maximumKnocks; i ++) {/ / normalisera tiden mellan smällar. (den längsta tiden = 100) secretCode [i] = karta (knockReadings [i], 0, maxKnockInterval, 0, 100); } saveSecretKnock(); spara resultatet till EEPROM programModeActive = false; playbackKnock(maxKnockInterval); returnera false; } om (currentKnockCount! = secretKnockCount) {/ / lättast kolla först. Om antalet smällar är fel, inte låsa upp. returnera false; } / * Nu jämför vi de relativa intervallerna av våra smällar, inte absoluta tiden mellan dem. (dvs: om du gör samma mönster långsamt eller snabbt det fortfarande bör öppna dörren.) Detta gör det mindre kräsen, som samtidigt gör det mindre säkert kan också göra det mindre av en smärta att använda om du är tempot är lite långsamt eller snabbt. * / int totaltimeDifferences = 0; int timeDiff = 0; för (jag = 0; jag < maximumKnocks; i ++) {/ / normalisera gånger knockReadings [i] = karta (knockReadings [i], 0, maxKnockInterval, 0, 100); timeDiff = abs (knockReadings [i] - secretCode[i]); if (timeDiff > rejectValue) {/ / individens värde för långt ur smäll. Ingen åtkomst för denna knock! returnera false; } totaltimeDifferences += timeDiff; } / / Det kan också misslyckas om hela är också felaktig. om (totaltimeDifferences / secretKnockCount > averageRejectValue) {return false;} return true;} läser den Hemlig knackning från EEPROM. (om någon.) void readSecretKnock() {byte läsning; int i, behandlingen = EEPROM.read(0); om (läser == eepromValid) {/ / endast läsa EEPROM om signatur byte är korrekt. för (int jag = 0; jag < maximumKnocks; i ++) {secretCode [i] = EEPROM.read(i+1);}}} //saves ett nytt mönster för eepromvoid saveSecretKnock() {EEPROM.write (0, 0); / / rensa ut signaturen. På så sätt vet vi om vi inte avsluta skriva framgångsrikt. för (int jag = 0; jag < maximumKnocks; i ++) {EEPROM.write (i + 1, secretCode[i]);} EEPROM.write (0, eepromValid); alla bra. Skriv signaturen så att vi vet det är allt bra.} Spelar upp mönstret för knock i blinkar och beepsvoid playbackKnock (int maxKnockInterval) {digitalWrite (ledPin, låg); delay(1000); digitalWrite (ledPin, hög); kvittra (200, 1800), för (int jag = 0; jag < maximumKnocks; i ++) {digitalWrite (ledPin, låg); / / bara slå det på om det finns en fördröjning om (secretCode [i] > 0) {fördröjning (karta (secretCode [i], 0, 100, 0, maxKnockInterval)); / / expandera tiden tillbaka ut till vad det var. Ungefär. digitalWrite (ledPin, hög); KVITTER (200, 1800); {}} digitalWrite (ledPin, låg);} Behandlar knock dröjsmål thingy.void knockDelay() {int itterations = (knockFadeTime / 20); / / Wait för topp att försvinna innan du lyssnar på nästa en. för (int jag = 0; jag < itterations; i ++) {delay(10); analogRead(knockSensor); / / Detta är gjort för att försöka desarmera sensorns analog kondensator som ger felaktiga avläsningar på hög impedans sensorer. delay(10);}} / / spelar en icke-musikaliska ton i piezo. / / speltid = millisekunder för att spela tonen / / fördröjningstid = tid i mikrosekunder mellan fästingar. (mindre = högre tonhöjd ton.) void KVITTER (int speltid, int fördröjningstid) {lång loopTime = (speltid * 1000L) / fördröjningstid; pinMode(audioOut, OUTPUT); för (int jag = 0; jag < loopTime; i ++) {digitalWrite (audioOut, hög); delayMicroseconds(delayTime); digitalWrite (audioOut, låg);} pinMode (audioOut, ingång);}
För de nyfikna, här är en snabb sammanfattning av vad den koden gör: det initierar allt, ange lämpliga indata och utdata stift och laster sparade slå mönster (om någon) från EEPROM. Efter allt är initierad avlyssnar en stegring på piezo-sensor.
När dess över en viss tröskel räknas den som en "knock".
När den hör en knock startar en timer och sedan lyssnar efter fler smällar.
När det blir en annan knock sparar det tiden mellan smällar till en matris.
När det finns inga fler smällar (det finns minst 1,2 sekunder utan en knock) kontrollerar den om sekvensen är korrekt.
Det gör detta genom att normalisera tiden mellan smällar, som gör dem i förhållande till varandra, inte de exakta millisekunder mellan dem. Så den längsta tid mellan smällar blir 100, hälften som tid blir 50, etc.
Att använda språket av musik hela anteckningar är 100, halv anteckningar är 50, kvartstoner är 25, etc.
Jämför dessa värden till den lagrade knock.
Om de matchar (eller nästan matchar) låsa öppnar för ett par sekunder och sedan går tillbaka till #2. Om knock inte matchar, det blinkar en ljus för misslyckande och sedan går tillbaka till #2.It gör andra saker också, som Läs på knappen för att se om det ska programmera en ny knock, etc.
Koden är frikostigt kommenterade och men här är ett par saker du kan vara intresserad av att ändra:
Kopiera koden
int tröskel = 3; (rad 29)
Om knacksensor är för känslig kan du prova att höja detta värde. Värden under 10 arbetar oftast bäst, men värden upp till 250 har varit kända för att arbeta. (Om du behöver höja detta över 250 då du sannolikt har något fel med din krets eller komponenter.)
Kopiera koden
CONST int rejectValue = 25; const int averageRejectValue = 15. (linje 30-ish)
Dessa två procenttal anger hur exakt knock måste vara att låsa upp. Att öka dessa siffror kan en sloppier knäck att arbeta. Sänka dem kräver en mer strikt knock.