Hello Arduino Community! We're Arduino beginners trying to make a mechanism that opens a door when a certain pattern of knocks is made. The project works perfectly...except when it's plugged into any sort of external power.
The Problem:
We're using analogRead to read voltage from a vibration sensor. When the Arduino was powered by a computer USB port or by a nearly-dead 9V battery, it works perfectly. It reads between 0-6 when it isn't vibrating and gets up to about 60 with a strong knock. However, when we tried to power the Arduino by hooking the USB cable up to a 5V 1 Amp USB charger, or when we plugged it into a 9VDC 800mA converter, we got values that fluctuated between 0 and about 450. When the calls to analogRead have a less-than-30-ms or so delay between them, the output fluctuated between 0 and about 450 many times a second. When the delay was longer, we saw a jump to much slower fluctuation that was very regular in its period, taking about 4 seconds for a cycle. The values were not affected by knocking or vibrating the sensor in any way. Everything works perfectly again the moment we unplug the Arduino from the wall and put it back on the computer’s USB power.
The Setup:
We’re using an Arduino Uno and this sensor. One end of the sensor is plugged into A0, the other is plugged into Gnd. Three Mega-Ohm resistors connected in series also connect A0 to Gnd. It’s the same setup used in the Arduino Knock Tutorial but with 3 Mega-Ohm resistors instead of 1. The only other thing plugged into the Arduino is a servo. The wires going to the sensor are about a foot long. We used alligator clips to attach to the sensor leads.
Things We Have Already Tried:
-Attaching wires from the rest of the analog ports to ground
-Disconnecting the servo
-Commenting out all the Serial communication, including begin()
Code and Output:
Here’s a simple program to print analogRead every 50 ms.
const int knockSensor = A0; // the piezo is connected to analog pin 0
int sensorReading = 0; // variable to store the value read from the sensor pin
void setup() {
analogReference(DEFAULT);
pinMode(A0, INPUT);
Serial.begin(9600); // use the serial port
}
void loop() {
// read the sensor and store it in the variable sensorReading:
sensorReading = analogRead(knockSensor);
Serial.println(sensorReading);
delay(50); // delay to avoid overloading the serial port buffer
}
Here is some output from running this program when the Arduino is powered by the external 9VDC power supply. You can see the periodic fluctuations in the readings between 0 and 400.
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
3
44
44
78
96
122
160
203
230
269
315
348
359
369
387
412
418
403
391
366
341
308
282
257
228
190
116
40
1
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
14
14
65
93
121
155
212
269
304
360
406
415
403
401
417
442
434
424
400
379
348
317
291
269
237
193
94
35
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
10
10
63
88
109
141
185
226
245
294
339
363
358
361
382
405
400
387
371
349
323
290
267
243
215
179
95
40
3
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
40
40
76
97
120
159
205
237
272
320
358
373
384
395
421
434
415
407
378
353
318
289
263
237
198
139
48
9
0
0
0
0
0
0
Though it’s probably not relevant to my problem, for completeness’ sake here’s the full code for sensing knock patterns and opening the door.
#include <Servo.h>
//sensing variables
const int knockSensor = A0; //knock input
int threshold = 10; // threshold value to decide when the detected sound is a knock or not
const int lower_thresh = 9;
const int CYCLES_REST =30;
int averageReading = 0;
int restCounter = 0;
//Pattern logic variables
int cycle = 0; //how log it's been since knock started
const int TIMEOUT = 500;
const float TIMING_ERROR = 0.2;
boolean currentlyKnocking = false;
float scalar = 1;//scales pattern to
float pattern[] = { //The knock pattern
1, 1,1}; //knock-knock-knock
int patternLength = 3;
int currentIndex;
boolean onTarget = true; //timing is good.
boolean knockCompleted = false;
const int KNOCK_RESET_TIME = 500;
boolean knockAllowed = true;
//Servo Variables
Servo myservo; // create servo object to control a servo
int servoPin = 9;
void setup(){
Serial.begin(9600); //Begin serial communcation
normalizePattern();
getaverageReading();
//myservo.attach(servoPin);
// myservo.write(0);
threshold = averageReading + 10;
}
void loop(){
if(knockAllowed)
{
if(currentlyKnocking)
{
cycle++;
if(cycle > TIMEOUT)
{
currentlyKnocking = false;
// Serial.println("Knock Pattern TimedOut");
}
}
if(checkKnock()){
//knock has started
if(!currentlyKnocking)
{
startKnock();
}
else
{
recordCycle(cycle);
if(knockCompleted)
{
openDoor();
currentlyKnocking = false;
cycle = KNOCK_RESET_TIME;
// Serial.println("Knock Completed Correctly");
knockAllowed = false;
return;
}
else if(!onTarget)
{
// Serial.println("Knock Abort!");
currentlyKnocking = false;
cycle = KNOCK_RESET_TIME;
knockAllowed = false;
return;
}
// Serial.println("Knock");
cycle = 0;
}
// Serial.println("high");
}
}
else
{
if(--cycle < 0)
{
knockAllowed = true;
// Serial.println("Ready For next Knock");
}
}
delay(5);
}
void recordCycle(int gap)
{
if(currentIndex == 0)
{
scalar = gap;
}
else
{
float adjusted = pattern[currentIndex] * scalar;
if(gap > adjusted * (1 - TIMING_ERROR) &&
gap < adjusted * (1 + TIMING_ERROR))
{
//correct timing
if(currentIndex + 1 == patternLength)
knockCompleted = true;
}
else
{
//wrong timing
onTarget = false;
}
}
currentIndex++;
}
void startKnock()
{
//Serial.println("Knock Pattern Started");
currentlyKnocking = true;
currentIndex = 0;
onTarget = true;
knockCompleted = false;
cycle = 0;
}
boolean checkKnock()
{
// read the sensor
int sensorReading = analogRead(knockSensor);
if (restCounter <= 0 && sensorReading >= threshold) {
restCounter = CYCLES_REST;
return true;
}
else if(sensorReading <= averageReading + 2) restCounter--;
return false;
}
void normalizePattern()
{
if(pattern[0] != 1)
{
float scaleBy = 1/pattern[0];
for(int i = 0; i < patternLength; i++)
{
pattern[i] *= scaleBy;
}
}
}
void getaverageReading()
{
int total = 0;
for(int i = 100; i > 0; i--)
{
int sensorReading = analogRead(knockSensor);
total+= sensorReading;
delay(10);
}
averageReading = (total / 100.0 + .5);
}
void openDoor()
{
myservo.attach(servoPin);
myservo.write(180);
delay(2000);
myservo.write(0);
delay(1000);
myservo.detach();
}
This problem has been really discouraging for us today after so much success in assembling our contraption. To reiterate, the whole thing works perfectly, just as long as it's plugged into the computer USB port. Any help is much appreciated!