Waiting for parts to arrive to test my sketch and looking for a quick evaluation

Hi forums,

I’ve had my Arduino for barely a month and I’m already emptying my wallet on things to do with it. As a mechatronic engineering undergraduate the possibilities seem endless and it’s really enabling me to try out all things automation that I could only dream of before!

Beyond making leds flash and transistors switch DC motors on and off in my labs at uni I decided to undertake a project with a slightly bigger scope at home. It’s a mechanism to autonomously open our roller door to the backyard for our dog, to save one of us from having to get up and go open the door every goddamn 10 minutes.

The implementation is based around using a mic and frequency spectrum analyser chip MSGEQ7 datasheet to ‘listen’ to when the dog barks at the closed door as she does, and compare it to a ‘master profile’ bark. If the signal is a match, the OpenDoor() function is called. This switches a DC motor using an H-bridge to hopefully open the door a decent amount, and then waits a few seconds to let it close again with the help of a weight (sometimes roller doors come with an auto-closing weight anyway so the mechanics weren’t too hard to think about).

Additionally, the Arduino only ‘listens’ for a bark when an object/the dog is within a decent proximity to an ultrasonic sensor to stop random dog barks from accidentally opening the door. So this sets a flag before looking for a signal, then comparing the signal and acting accordingly.

I’ve yet to receive all the parts for this as the MSGEQ7 chip wasn’t locally available so I had to get it from China through ebay. In that time I wrote a sketch, and it compiles successfully so fingers crossed there won’t be too many issues when I get around to trying it out.

So ‘get to the goddamn point’ I hear you say - I would really appreciate anyone more experienced having a look through the code if they have a spare moment, in case I missed anything or if there is a glaring flaw in my program logic. Many thanks in advance! Please find attached my sketch, I will also put the text underneath here.

(P.s. disclaimer, if I really need it: feel free to use parts or all of my code if you want, I claim no safe operation guarantees if you decide to try anything - also credits to Tim Eckel for his code and NewPing library that I used for the ultrasonic sensor)

barkdooropener.ino (6.57 KB)

//Stuff for ultrasonic sensor from downloaded library///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <NewPing.h>
#define TRIGGER_PIN  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     11  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 150 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

int distance;                // my distance of object to sensor (namely the dog) in cm
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define motorForwardPin 3    // PWM pin H3 to set high if you want the door to open
#define motorReversePin 4    // PWM pin H4 to set high as the door closes
#define motorSpeed 127       // duty cycle level to write to the PWM pins (0 < motorSpeed < 255) when opening and closing the door, will need to test a good value but will set to halfway for now
#define doorHolder 20        // duty cycle to hold the door open - will need to test a value that provides a torque to balance the door closer weight but will try a small value of 20 to start
#define doorOpenTime 1200    // how long to run the motor for while opening the door. Dependant on the motor speed, pulley size, forward duty cycle so will need to test all these simultaneously
#define openDelay 7000       // door will remain open for 7 seconds until it gets closed again. Should be enough time but will test
#define doorCloseTime 1200   // theoretically door should close for the same time it opens to go the same distance forwards and backwards, but will use two constants to test. Could use
                             // slightly less time for closing, or slightly more power for opening (as the motor is under load during opening)
void OpenDoor();             // prototype for OpenDoor()

#define MSGEQ7_out 0         // pin for reading analog signal given by chip, choosing ADC0/PF0 for now
#define chipStrobePin 0
#define chipResetPin 1       // defining MSGEQ7 strobe pins and reset pins as PA0/PA1
int bandSignals[7];          // container for analog signals from output of MSGEQ7 spectrum analyser chip
int checkResult = 0;         // result of calling AudioCheck(), triggers OpenDoor if equal to 1
void ReadAudio();             // function to grab spectrum and open door if it reports successful match to chosen bark. Is continuously called when dog is in suitable range of ultrasonic sensor

#define TOL 20               // tolerance for the signal result (0 < signal < 1023). Will change as needed
int masterProfile[7] = {0,0,0,0,0,0,0};  // levels to check signal against to allow door to open or not. Will edit when I can capture a profile
int AudioCheck();            // prototype for AudioCheck() which checks audio signal against master profile

void setup()
{
  // put your setup code here, to run once:
  DDRH = 0xFF;      // port H will be used for PWM output for the motor
  DDRA = 0xFF;      // port A used for controlling the MSGEQ7 channel select/strobe and reset pins
  DDRF &= ~(1 << MSGEQ7_out);  // PF0/ADC0 set to input to receive audio signal from the chip to send to the Arduino
  delay(100);  // short delay
}

void loop()
{
  delay(50);                      // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
  unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
  distance = uS/US_ROUNDTRIP_CM;  // distance to dog
  while(distance != 0)  // while distance is within the maximum set distance MAX_DISTANCE (as defined in the NewPing setup ^), allow listening of the bark to commence
  {
    ReadAudio();  // continuously read audio signals into the result array bandSignals
    checkResult = AudioCheck();  // function to check the signals in bandSignals against the master profile, returns success or failure and opens door accordingly
    if(checkResult == 1)
    {
      OpenDoor();
    }
  }
}

void OpenDoor()  // function will control a DC motor using an H bridge to open and close the door via a winch system
{
  analogWrite(motorForwardPin, motorSpeed);  // begins opening the door
  delay(doorOpenTime);  // runs the motor for this long
  analogWrite(motorForwardPin, doorHolder);  // 'stalls' the motor, holds door open
  delay(openDelay);  // leaves door open for a little while
  analogWrite(motorForwardPin, 0); 
  analogWrite(motorReversePin, motorSpeed);  // motor now goes backwards, may not even need to power the motor in reverse if the door closer weight is heavy enough
  delay(doorCloseTime); 
  analogWrite(motorReversePin, 0);  // switch off the motor
  delay(500);  // short delay
}

void ReadAudio()  // function to read the analog output of the MSGEQ7 chip and store the data or profile in an array to be evaluated later
{
  int i;
  for(i=0; i<7; i++)  // read the 7 bands
  {
    bandSignals[i] = analogRead(MSGEQ7_out);  // get analog signal for each band and store in the array, will be 0 < bandSignals[i] < 1023
    PORTA |= (1 << chipStrobePin);  // changing channel to receive on by flipping the strobe pin/chooses different band pass filter internally in the chip
    delay(1);
    PORTA &= ~(1 << chipStrobePin);
    delay(1);
  }
  PORTA |= (1 << chipResetPin);  // flipping chip's reset pin to return to reading first band when ReadAudio() is next called
  delay(1);
  PORTA &= ~(1 << chipResetPin);
  delay(1);
}

int AudioCheck()
{
  if( ( bandSignals[0] <= (masterProfile[0] + TOL)) && (bandSignals[0] >= (masterProfile[0] - TOL)) &&
      ( bandSignals[1] <= (masterProfile[1] + TOL)) && (bandSignals[1] >= (masterProfile[1] - TOL)) &&
      ( bandSignals[2] <= (masterProfile[2] + TOL)) && (bandSignals[2] >= (masterProfile[2] - TOL)) &&
      ( bandSignals[3] <= (masterProfile[3] + TOL)) && (bandSignals[3] >= (masterProfile[3] - TOL)) &&
      ( bandSignals[4] <= (masterProfile[4] + TOL)) && (bandSignals[4] >= (masterProfile[4] - TOL)) &&
      ( bandSignals[5] <= (masterProfile[5] + TOL)) && (bandSignals[5] >= (masterProfile[5] - TOL)) &&
      ( bandSignals[6] <= (masterProfile[6] + TOL)) && (bandSignals[6] >= (masterProfile[6] - TOL)) )  // checking input signal against the master profile, to within a tolerance TOL
  {
    checkResult = 1;  // if bark is a match, let the door open otherwise reject the bark and wait to try again
  }
  else checkResult = 0;
  
  return checkResult;
}
  distance = uS/US_ROUNDTRIP_CM;  // distance to dog
  while(distance != 0)  // while distance is within the maximum set distance MAX_DISTANCE (as defined in the NewPing setup ^), allow listening of the bark to commence
  {
    ReadAudio();  // continuously read audio signals into the result array bandSignals
    checkResult = AudioCheck();  // function to check the signals in bandSignals against the master profile, returns success or failure and opens door accordingly
    if(checkResult == 1)
    {
      OpenDoor();
    }
  }

Trouble brewing.

You don't regain "distance" inside the loop, so that will loop infinitely.

First of all... your idea is simply great and funny!

Anyway, i think that only you could REALLY understand if something is missing in the code... because you wrote it! Do you need to "fill the time" before the chip's delivery? Try to improve your idea with some new functions!

A counter that counts how much time the dog goes out in a day and let you see it on a little LCD monitor? A counter that counts how much time your dog spent out in a day (so you could see her happiness :roll_eyes: )?

Many thanks to all the super fast replies, I honestly didn’t expect such a quick response so thank you.

@Nick, thanks for pointing that out, I guess I must’ve forgotten it was a while loop or something 10 minutes after writing it, that is a rather obvious issue now. Fixed it by re-reading distance again within the loop.

@Pet0 tyvm! Honestly it was nothing more than an attempt at a solution to an existing problem. I will confess though yes it is kind of filling the time before receiving the parts lol haven’t yet hit my ‘beginners - intermediate’ writer’s block yet so I can’t seem to get enough Arduino!

I’m just at this stage wanting to test the bare functionality of the code, but I think I will write some more lines and functions with other variables in a separate textfile to gather statistics later as I think it will be cool data to examine. Thanks all again for the advice, and I will update this thread with the results if I get it working.