I've been working on a little project on an Arduino and I need some help with making the code more efficient / cleaner. I really don't like the three for
loops and feel like I could condense them somehow.
How it works:
- An HC-05 Bluetooth module is connected via a serial connection to an Arduino Micro.
- The Arduino filters the serial data and extracts the MAC addresses that it finds.
- The discovered MAC addresses are compared against a white-list.
- Once a white-listed device comes in range of the Bluetooth module AND passes a light barrier, the door opens.
- The door can only be re-opened if either a NEW device comes in range, or if the already entered device has left the Bluetooth range for at least 10 seconds and re-enters.
#include <SoftwareSerial.h>
#include "Timer.h"
SoftwareSerial mySerial(10, 11); // RX, TX
Timer t;
// Pinbelegung
int keyPin = 13;
int detectionPin = 8;
int powerPin = 9;
int doorPin = 4;
// Wert von detectionPin Eingang
int detectionPinRead;
// Serielle Daten
String serialData;
// Rausgefilterte MAC Addresse
String mac;
// Zugangsarrays
const char* whitelist[2] = {"+INQ:BCF5:AC:74DDB7", "+INQ:1068:3F:E1081F"};
int time[2] = {0, 0};
boolean entered[2] = {false, false};
// Zeit seit dem Start
unsigned long currentTime;
// Zugangsbedingung
boolean detected;
boolean retrigger;
void setup() {
Serial.begin(38400);
while (!Serial) { ; }
mySerial.begin(38400);
pinMode(keyPin, OUTPUT);
pinMode(detectionPin, INPUT);
pinMode(powerPin, OUTPUT);
pinMode(doorPin, OUTPUT);
// Versetze Bluetoothmodul in AT Modus
digitalWrite(keyPin, HIGH);
delay(500);
digitalWrite(powerPin, HIGH);
delay(500);
mySerial.println("AT+INIT");
delay(500);
mySerial.println("AT+INQM=1,0,48");
delay(500);
mySerial.println("AT+INQ");
// Ein Scan dauert ca. 62 Sekunden. Starte alle 63 Sekunden einen neuen Scan
t.every(63000, startInq);
}
void loop() {
t.update();
currentTime = millis() / 1000;
//Wenn Serielle Daten verfügbar sind, lese so lange bis end of line
while (mySerial.available() > 0) {
char received = mySerial.read();
serialData += received;
if (received == '\n') {
mac = getToken(serialData, ',', 0);
// Debug
Serial.println(mac);
Serial.println(currentTime);
Serial.println(time[0]);
Serial.println(time[1]);
// Lese den Eingang aus. Wenn HIGH und retrigger ist verhindert, setze Zugangsbedingung
detectionPinRead = digitalRead(detectionPin);
if (detectionPinRead == HIGH && !retrigger) {
for (int i = 0; i < 2; i++) {
if (mac == whitelist[i]) {
detected = true;
retrigger = true;
break;
}
}
}
// Überprüfe ob MAC seit mindestens 10 Sekunden nicht mehr in Rechweite ist
for (int i = 0; i < 2; i++) {
if(mac == whitelist[i] && currentTime - time[i] >= 10) {
entered[i] = false;
retrigger = false;
break;
}
}
// Öffne Tür sobald Zugansbedingungen erfüllt sind
for (int i = 0; i < 2; i++) {
if (mac == whitelist[i]) {
time[i] = currentTime;
if (!entered[i] && detected) {
entered[i] = true;
openDoor();
break;
}
}
}
serialData = "\0";
}
}
}
String getToken(String data, char separator, int index) {
int found = 0;
int strIndex[] = {0, -1};
int maxIndex = data.length() - 1;
for(int i = 0; i <= maxIndex && found <= index; i++) {
if(data.charAt(i) == separator || i == maxIndex) {
found++;
strIndex[0] = strIndex[1] + 1;
strIndex[1] = (i == maxIndex) ? i + 1 : i;
}
}
return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}
void openDoor() {
digitalWrite(doorPin, HIGH);
delay(500);
digitalWrite(doorPin, LOW);
detected = false;
}
void startInq() {
mySerial.println("AT+INQ");
}