Go Down

Topic: I need a little help with my code (Read 3067 times) previous topic - next topic

Bavilo

Aug 06, 2014, 05:56 pm Last Edit: Aug 06, 2014, 10:43 pm by Bavilo Reason: 1
Hello everyone!

I am working on a little project that is basically a door opener with Bluetooth presence detection.
Here is how it works.

A HC-05 Bluetooth module is connected to an Arduino. The HC-05 is constantly inquiring near devices. Once a whitelisted device has been found the door will open and set the status for that device to "entered". Otherwise the door would constalty be opening.

Exactly here is the problem. Once the device has passed the door, and the device gets OUT of reach of the HC-05 I need the device status to be set back to "false".

But since the HC-05 is constantly inquiring and might find different devices I can not be sure to set the status of the correct device.

Here is what the output of the HC-05 will look like:

Code: [Select]
+INQ:BCF5:AC:74DDB7,5A020C,FFD2
+INQ:C829:2A:144E44,0,FFB7
+INQ:C829:2A:144E44,0,FFB7
+INQ:C829:2A:144E44,0,FFB9
+INQ:BCF5:AC:74DDB7,5A020C,FFD6
+INQ:BCF5:AC:74DDB7,5A020C,FFD7
+INQ:BCF5:AC:74DDB7,5A020C,FFD6
+INQ:BCF5:AC:74DDB7,5A020C,FFD8
+INQ:BCF5:AC:74DDB7,5A020C,FFD7
and so on...


Here is my code:

Code: [Select]

int doorPin = 13;
int commaPosition;

String serialData;
String michaelMac = "+INQ:BCF5:AC:74DDB7\n";
String maikeMac = "+INQ:ABCD:AC:74DDB7\n";

unsigned long currentTime, michaelTime, maikeTime;

boolean michaelEntered, maikeEntered;

void setup() {
  Serial.begin(9600);   
  Serial.println("Waiting for input");
  pinMode(doorPin, OUTPUT);   
  michaelTime = currentTime;
  maikeTime = currentTime;
}

void loop() {
  currentTime = millis();
  while (Serial.available() > 0) {
    char received = Serial.read();
    serialData += received;

    if (received == '\n') {
      String mac = getToken(serialData, ',', 0);
      Serial.print(mac); //debug

      Serial.println(currentTime); //debug
      Serial.println(michaelTime); //debug
      Serial.println(maikeTime); //debug

      if(mac != michaelMac && currentTime - michaelTime >= 10000) { 
        Serial.println("Michael is not in reach!");
        michaelEntered = false;
      }       
      if(mac != maikeMac && currentTime - maikeTime >= 10000) { 
        Serial.println("Maike is not in reach!");
        maikeEntered = false;
      }

      if (mac == michaelMac) {
        michaelTime = currentTime; 
        if (michaelEntered == false) {     
          Serial.print("MAC from Michael found: " + michaelMac);
          openDoor();
          michaelEntered = true;   
        }       
      }       
      if (mac == maikeMac) {
        maikeTime = currentTime; 
        if (maikeEntered == false) {     
          Serial.print("MAC from Maike found: " + maikeMac);
          openDoor();
          maikeEntered = true;   
        }       
      } 
     
      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(1000);
  digitalWrite(doorPin, LOW);
}



I hope someone can push me in the right direction.
If I need to explain anything, please let me know!

Thanks!

johnwasser

I would note the time that each whitelist entry was last seen.  Scan the list occasionally (every second?) and if the the entry is marked "entered" and has not been seen for more than 30 seconds, mark it not-entered.
Send Bitcoin tips to: 1G2qoGwMRXx8az71DVP1E81jShxtbSh5Hp

Bavilo

#2
Aug 06, 2014, 07:47 pm Last Edit: Aug 06, 2014, 10:42 pm by Bavilo Reason: 1

I would note the time that each whitelist entry was last seen.  Scan the list occasionally (every second?) and if the the entry is marked "entered" and has not been seen for more than 30 seconds, mark it not-entered.


Thanks for the advice!


Robin2

You seem to be saving millis() into time and into michaelTime in the same loop so inevitably they are the same and subtracting them gives 0. The problem is exacerbated by dividing millis() by 1000.

I can't suggest a solution because I'm not sure what you want to do. For example do you want to save millis() when Michael enters the room and compare that value to the current value of millis() to see how long he has been there? Or do you want to record millis() within setup() and find out how long was it after the Arduino started when Michael entered?

I suggest you use millis() in its raw state and only divide by 1000 when you actually want to display a value.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Bavilo


You seem to be saving millis() into time and into michaelTime in the same loop so inevitably they are the same and subtracting them gives 0. The problem is exacerbated by dividing millis() by 1000.

I can't suggest a solution because I'm not sure what you want to do. For example do you want to save millis() when Michael enters the room and compare that value to the current value of millis() to see how long he has been there? Or do you want to record millis() within setup() and find out how long was it after the Arduino started when Michael entered?

I suggest you use millis() in its raw state and only divide by 1000 when you actually want to display a value.

...R


Please check the updated code.

If the MAC of Michael is found michaelTime will be set equal to currentTime. This will open the door and set michaelEntered to true.
If MAC of Michael keeps coming up within 10 seconds, nothing will happen, the door will not open again.

But if MAC of Michael does not come up within 10 seconds michaelEntered is set to false.
When MAC of Michael now comes up again, the door will be able to be opened again.


That's basically what I wanted to accomplish.

If there's an easier, more elegant way of doing this. Please let me know :D


Robin2

This is not the best way to use millis()
Code: [Select]
if (currentTime >= (michaelTime + 10))

It should be

Code: [Select]
if (currentTime - michaelTime >= 10)

This way the code will properly handle the situation when millis() rolls over from 2^32 to 0.

...R

Two or three hours spent thinking and reading documentation solves most programming problems.

Bavilo


This is not the best way to use millis()
Code: [Select]
if (currentTime >= (michaelTime + 10))

It should be

Code: [Select]
if (currentTime - michaelTime >= 10)

This way the code will properly handle the situation when millis() rolls over from 2^32 to 0.

...R




Thanks!

I have updated the code on the first post. I have also added another MAC. I'm certain that this is far from pretty. But it works. Any suggestions to clean it up?

AWOL

Quote
I have updated the code on the first post

Please don't do that - it can make the thread hard to follow.
"Pete, it's a fool (who) looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

Bavilo


Quote
I have updated the code on the first post

Please don't do that - it can make the thread hard to follow.


I'm sorry. Won't happen again.

Bavilo

Here is the latest working code:

Code: [Select]
#include <SoftwareSerial.h>
#include "Timer.h"

SoftwareSerial mySerial(10, 11); // RX, TX

Timer t;

int keyPin = 8;
int powerPin = 9;
int doorPin = 13;
int commaPosition;

String serialData;
String mac;
String michaelMac = "+INQ:BCF5:AC:74DDB7";

unsigned long currentTime, michaelTime;

boolean michaelEntered;

void setup() {
  Serial.begin(38400);   
  Serial.println("Waiting for input");
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  mySerial.begin(38400);

  pinMode(doorPin, OUTPUT); 
  pinMode(keyPin, OUTPUT); 
  pinMode(powerPin, OUTPUT);

  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");

  michaelTime = currentTime;

  t.every(63000, startInq);
}

void loop() {
  t.update();
  currentTime = millis();
  while (mySerial.available() > 0) {       
    char received = mySerial.read();
    serialData += received;       

    if (received == '\n') {
      mac = getToken(serialData, ',', 0);
      serialData = "\0";

      Serial.println(mac); //debug
      Serial.println(currentTime); //debug
      Serial.println(michaelTime); //debug   

      if(mac == michaelMac && currentTime - michaelTime >= 10000) { 
        Serial.println("Michael is not in reach!");
        michaelEntered = false;
      }

      if (mac == michaelMac) {
        michaelTime = currentTime;
        if (michaelEntered == false) {     
          Serial.print("MAC from Michael found: " + michaelMac);
          openDoor();
          michaelEntered = true;   
        }
      }

    }
  }
}

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(5000);
  digitalWrite(doorPin, LOW);
}

void startInq() {
  mySerial.println("AT+INQ");
}








Yes...it's very sloppy. Can anyone help me clean it up?

Go Up