Hey guys,
I've been trying to get things to work but I'm running into a strange problem. (Bye the way, I'm using a 5V 16 MHz Arduino Pro 328)
I'm building a kind of battery driven digital level tool, if the tool is within lowLim
degrees from level, a green LED lights (inLEDPin
) and a buzzer sounds (inBuzzPin
, otherwise one of two red LED's (outLEDPinLeft
or outLEDPinRight
) are lit, indicating in which direction to tilt the tool in order for it to be level. For the code, see below. First I've build the level part, which works like a charm. Now I added the part where the Arduino can 'control' its own power (no measuring of the LiPo voltage is taking place yet) and that's where it goes wrong.
The power to the arduino is controlled by two LH 1540 relays connected in parallel. The first is connected to a pushbutton momentary switch, the second to digital output 6. If I push the pushbutton for a second or so, the Arduino has powered up and sets pin 6 high, so I can release the switch and it keeps working. So far so good. However, if I then tilt the test setup to where the tilt angle goes beyond lowLim
, the moment the indicator LED's are switched, the signal from pin 6 drops to zero too, and only comes back up after a little while. Does anybody see what I'm doing wrong?
FYI: I currently only have the green led attached through a NPN transistor with a 10k base resistor, powering the led from the LiPo. The LH1540 is attached to output 6 with a 1 k current limiting resistor in series. Furthermore, the ADXL 345 is powered from the board. The LiPo's voltage doesn't drop at all when switching.
//////////////////////////////////////////////////////////////////
//Bildr design modified by Doornroos
//////////////////////////////////////////////////////////////////
//Analog read gravity sensor pins
const int xPin = 0;
const int yPin = 1;
const int zPin = 2;
//Signal out pins
const int outLEDPinRight = 9;
const int outLEDPinLeft = 8;
const int inLEDPin = 10;
const int inBuzzPin = 7;
const int battOn = 6;
//Running average filter constants
const int numReadings = 10;
double yReadings[numReadings]; // the readings from the analog input
int index = 0; // the index of the current reading
double ySum = 0; // the running total
double yAvg = 0; // the average
//The minimum and maximum values that came from
//the accelerometer while standing still
//You very well may need to change these
int xMinVal = 388;
int xMaxVal = 622;
int yMinVal = 397;
int yMaxVal = 629;
int zMinVal = 398;
int zMaxVal = 609;
//In range lower and upper bounds (degrees)
int lowLim = 1;
int upLim = 45;
//to hold the caculated values
double x;
double y;
double z;
void setup(){
Serial.begin(9600);
pinMode(outLEDPinRight, OUTPUT);
pinMode(outLEDPinLeft, OUTPUT);
pinMode(inLEDPin, OUTPUT);
pinMode(inBuzzPin, OUTPUT);
pinMode(battOn, OUTPUT) ;
//Set battOn high
digitalWrite(battOn, HIGH);
//Initialize Red LEDs off
digitalWrite(outLEDPinRight, LOW);
digitalWrite(outLEDPinLeft, LOW);
//Sound buzzer And blink green light to indicate ON
int nTimes = 3;
for (int i = 1; i <= nTimes; i++) {
digitalWrite(inLEDPin, HIGH);
digitalWrite(inBuzzPin, HIGH);
delay(500);
digitalWrite(inLEDPin, LOW);
digitalWrite(inBuzzPin, LOW);
delay(500);
}
//Initialize readings to zero
for (int ind = 0; ind < numReadings; ind++)
yReadings[ind] = 0;
}
void loop(){
//read the analog values from the accelerometer
int xRead = analogRead(xPin);
int yRead = analogRead(yPin);
int zRead = analogRead(zPin);
//convert read values to degrees -90 to 90 - Needed for atan2
int xAng = map(xRead, xMinVal, xMaxVal, -90, 90);
int yAng = map(yRead, yMinVal, yMaxVal, -90, 90);
int zAng = map(zRead, zMinVal, zMaxVal, -90, 90);
//Caculate 360deg values like so: atan2(-yAng, -zAng)
//atan2 outputs the value of -? to ? (radians)
//We are then converting the radians to degrees
x = RAD_TO_DEG * (atan2(-yAng, -zAng) + PI);
y = RAD_TO_DEG * (atan2(-xAng, -zAng) + PI);
z = RAD_TO_DEG * (atan2(-yAng, -xAng) + PI);
//Any correction or zeroing operations
y = y + 1.5;
//Map values between -180 and 180
if (y > 180){
y = y - 360;
}
//Store y-value to yReading array and calculate average:
//Substract last reading from ySum
ySum = ySum - yReadings[index];
//Store y value in array
yReadings[index] = y;
//Add reading to ySum
ySum = ySum + yReadings[index];
//Advance to next position of array
index = index + 1;
//If end of array is reached
if (index >= numReadings)
// wrap around to beginning
index = 0;
//Calculate average y value
yAvg = ySum / numReadings;
//Test the rotation around the x-axis and adjust signal outputs accordingly
if (abs(yAvg) <= lowLim) {
digitalWrite(inLEDPin, HIGH);
digitalWrite(inBuzzPin, HIGH);
digitalWrite(outLEDPinRight, LOW);
digitalWrite(outLEDPinLeft, LOW);
//Serial.println("Status: GREEN");
}
else if (upLim > abs(yAvg) && yAvg < -lowLim) {
digitalWrite(inLEDPin, LOW);
digitalWrite(inBuzzPin, LOW);
digitalWrite(outLEDPinRight, HIGH);
digitalWrite(outLEDPinLeft, LOW);
//Serial.println("Status: RED");
}
else if (upLim > abs(yAvg) && yAvg > lowLim) {
digitalWrite(inLEDPin, LOW);
digitalWrite(inBuzzPin, LOW);
digitalWrite(outLEDPinRight, LOW);
digitalWrite(outLEDPinLeft, HIGH);
//Serial.println("Status: RED");
}
else { //Set all pins to LOW
digitalWrite(inLEDPin, LOW);
digitalWrite(inBuzzPin, LOW);
digitalWrite(outLEDPinRight, LOW);
digitalWrite(outLEDPinLeft, LOW);
//Serial.println("Status: ELSE");
}
delay(10); //To ensure stable functioning
}