Help me count squirrels (Light sensor + attachInterrupt)

I am working on a long project and I'm fairly new to arduino.
I cannot seem to get the light sensor to work, when it is below than 150 the LED should turn on but the exact opposite happens?? (I need to be able to explain the code so I cannot just reverse the if statement)
I also cannot figure out how to count the number of times the LED turns on with the attachInterrupt() function, as it just prints 0 when i try to print squirrelCount. If anyone could help me or suggest an alternate method of counting the number of times the LED turns on (without just counting the time it is on) that would be so helpful.

#include <NewPing.h>
#include "MapFloat.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Light Sensor + Squrriel counter //(HEEEEEEEEEEEEEEEEEEEEEEEEEEELPMEEEEEEEEEEEEEEEEEEEEEEE)
const byte LED_Pin = 3;
int lightPin = A5;
int lightReading = 0;

int squirrelCount = 0;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Ultrasonic sensor 
#define SONAR_NUM 3      // Number of sensors.
#define MAX_DISTANCE 200 // Maximum distance (in cm) to ping. (Set MAX_DISTANCE = 200)

NewPing sonar[SONAR_NUM] = {   // Sensor object array, "Sonar" can be called back later
  NewPing(A0, A1, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping. 
  NewPing(A3, A2, MAX_DISTANCE), 
  NewPing(4, 5, MAX_DISTANCE)
};

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 2DOF Magnetometer simulator
#define PI 3.14159
// Constants for magnetometer - set as required
#define X_OFFSET 300
#define Y_OFFSET 200
#define X_SENS 1000
#define Y_SENS 1000
#define NOISE 50

// Other variables
long magX = 0;
long magY = 0;
int angle = 0;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Motor A (left) connections
int enA = 11;
int in1 = 8;
int in2 = 7;
// Motor B (right) connections
int enB = 12;
int in3 = 10;
int in4 = 9;

int reqSpeedA = 1;
int reqSpeedB = 1;

#define switchPin 7
int switchState = 0;      // variable for reading the state

int potX;
int potY;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Crash Switch
// constants won't change. They're used here to set pin numbers:
const byte crashPin = 2; // the number of the pushbutton pin
// variables will change:
volatile byte buttonState = 0; // variable for reading the pushbutton status

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////    
    
    
void setup()
{
 // Open COMMS channel
 Serial.begin(115200);
 Serial.println();
 Serial.println("Starting L293D motor driver...");

 // Set digital pins used for motor control
  pinMode(enA, OUTPUT);
  pinMode(enB, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  
 // Turn off motors - Initial state
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);
 pinMode(switchPin, INPUT); //initialize thebuttonPin as input
 
 // initialize the pushbutton pin as an input:
 pinMode(crashPin, INPUT);
 attachInterrupt(digitalPinToInterrupt(crashPin), crashSwitch, RISING);
 pinMode(LED_Pin, OUTPUT);
 attachInterrupt(digitalPinToInterrupt(LED_Pin), squirrelCounter, RISING);
}

void loop(){
  labviewInputs();
  lightSensor();
  setangle();
  calcvalues();
  printvalues();
  sonar_dis();
  driveMotors();
  delay(50);
  labviewOutputs();
}
    
int setangle()
{
 // To replicate the compass, take the potentiometer reading and convert to a heading
 // 0 deg -> 360 deg over pot rotation
 int potentiometer = analogRead(A4);
 angle = potentiometer*360.0/1023.0;
}
int calcvalues()
{
 // Trigonometry used to calculate equivalent magnetometer values for
 // given heading, values scaled and offset at user's discretion
 magX = cos(angle*PI/180)*X_SENS + X_OFFSET; //+ random(-NOISE,NOISE); (for producing graph)
 magY = sin(angle*PI/180)*Y_SENS + Y_OFFSET; //+ random(-NOISE,NOISE);
}
void printvalues()
{
 //Serial.print(magX);
 //Serial.print(" , ");
 //Serial.println(magY);
}
void sonar_dis(){
  for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through each sensor and display results.
    delay(50); // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
    int pings = sonar[i].ping_cm();
    //Serial.print(i);
    //Serial.print("=");
    //Serial.print(pings);
    //Serial.print("cm ");
  }
  //Serial.println();
}

void stopMotors(int w,int x,int y,int z){
  // Decelerate from maximum speed to zero
  for (int i = w; i >= 0; --i) {
    analogWrite(x, i);
    delay(10);
  }
  // Now turn off motors
  digitalWrite(y, LOW);
  digitalWrite(z, LOW);
}

void crashSwitch(){
  stopMotors(reqSpeedA,enA,in1,in2);
  stopMotors(reqSpeedB,enB,in3,in4);
  Serial.println("Vehicle crashed");
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//HELP ME PLEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEASE
void squirrelCounter(){
  squirrelCount++;
  Serial.print(squirrelCount);
  //return squirrelCount;
}
      
void lightSensor(){
  lightReading = analogRead(lightPin);
  //Serial.println(lightReading);
  if (lightReading<150){
    digitalWrite(LED_Pin,HIGH);
  }
  else if (lightReading>160){
    digitalWrite(LED_Pin,LOW);
  }
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void driveMotors() {
  if (reqSpeedA > 0)
  {
    // Drive motor anticlockwise
    Serial.print("Left motor anticlockwise speed at: ");
    Serial.println(reqSpeedA);
    analogWrite(in1, reqSpeedA);
    digitalWrite(in2, LOW);
  }
  else
  {
    // If zero then brake using:
    Serial.print("Left motor braking: ");
    Serial.println(reqSpeedA);
    stopMotors(reqSpeedA,enA,in1,in2);
  }
  if (reqSpeedB > 0)
  {
    // Drive motor anticlockwise
    Serial.print("Right motor anticlockwise speed at: ");
    Serial.println(reqSpeedB);
    stopMotors(reqSpeedB,enB,in3,in4);
  }
  else
  {
    // If zero then brake
    Serial.print("Right motor braking for: ");
    Serial.println(reqSpeedB);
    digitalWrite(in3, HIGH);
    digitalWrite(in4, HIGH);
  }
}

void labviewInputs() {
  int inputA;
  int inputB;
  while (Serial.available() > 1) {
    inputA = Serial.read();
    inputB  = Serial.read();
  }
  reqSpeedA = map(inputA,65,90,0,255);
  reqSpeedB = map(inputB,65,90,0,255);

}
void labviewOutputs(){
  potX = map(magX,-700,1300,65,90);
  potY = map(magY,-800,1200,65,90);
  Serial.write(potX);
  Serial.write(potY);
  Serial.println();
}

Sorry for the unrelated code, I'm not sure if they might be affecting each other

What light sensor? A Light Dependent Resistor (LDR)? How is yours wired?

Two ways to wire an LDR.

ldr wiring

Most LDRs will decrease in resistance with more light. So in scenario #1 the voltage at A0 (referenced to ground) will start near 5V in the dark and approach 0V as more light falls on the LDR. Scenario #2 is the opposite. In the dark the voltage at A0 will be near ground and approach 5V as more light falls on the LDR.

So reverse the wiring.

I usually wire my LDRs to ground and use the internal pullup as the load resistor. Just set the pinMode to INPUT_PULLUP.

Why are you using an interrupt for the squirrel counter? Why are you using serial print in an ISR? That will not work right as Serial.print uses interrupts and interrupts are disabled during an ISR. Set a flag when the count changes and, in loop(), check the flag and print if the flag is set and clear the flag. Since the squirrelCount variable is multi-byte you need to disable interrupts, copy the value of squirrelCount to another variable and re-enable interrupts, then print the copy. Otherwise squirrelCount could change while you are reading it and be corrupted.
And squirrelCount should be declared volatile.

Hi,
Can you just write some code to detect your light sensor.
If you wrote you code in stages you should have it already.

If not , then write code JUST for the light sensor and the serial monitor in the IDE.
Forget about interrupts, squirrels don't travel that fast.

You must establish the parameters of your light sensor before adding anymore code.
Observe the output as you change the light level.

A circuit diagram would also help, draw your circuit and post an image.
Please no fritzy pictures.

Tom... :grinning: :+1: :coffee: :australia:

1 Like

So I rewrote the code with just the light sensor, the LED still works in reverse of the if statement. I also tried to reverse the wires but same problem.

This is the circuit.

//Light Sensor
int LED_Pin = 3;
int lightReading = 0;
int lightPin = A0;

void setup()
{
  Serial.begin(9600);
  pinMode(LED_Pin, OUTPUT);
}

void loop()
{
  lightSensor();
}

void lightSensor(){
  lightReading = analogRead(lightPin);
  Serial.println(lightReading);
  if (lightReading<30){
    digitalWrite(LED_Pin,HIGH);
  }
  else if (lightReading>35){
    digitalWrite(LED_Pin,LOW);
  }
  if LED_pin = HIGH
}

Reverse the if statements. That sort of thing is what coding is all about!

Although it is a great idea to sit down and try to understand why one works one way, and the other works the other way. Looking at the value of lightReading will tell you a lot.

I do not believe that your led is wired to act like you want. When the LED_pin is HIGH there is 5v across the led and it will be off.

See this Adafruit tutorial for a more standard way to wire the led.
https://www.ladyada.net/learn/arduino/lesson3.html

Good point. In fact, the drawing shows that the output pin has no current limiting resistor, and may be destroyed.

Hopefully the drawing is wrong.

I think it has something to do with that I'm using an ambient light sensor, it seems to measure the reverse of what I thought it does, but I'm not sure.

The LDR resistance drops as the light intensity increases, so the voltage across the load resistor, and the ADC output increases.

But now, I can't be sure that the circuit drawing is correct. Did you download that from somewhere, or make it yourself?

In any case, the wiring shown is dangerous to the Arduino. Take the LED part of the circuit apart and start over with the link to the Adafruit tutorial. Otherwise you may destroy the Arduino.

Edit: if this is a simulation, then no worries.

Copied it off my lecture notes lol, I actually fixed the original problem. The signal wire was suppose to be on the ground side. Is it the low resistance that is dangerous?

Please post the correct wiring diagram.

The Arduino output pins support only very limited current flow (up to 20 mA is fine).


I moved the resistor to the anode (Which I think was pointless) but moving the signal wire (yellow) to the anode reversed the LED to fit the if statement

An output pin written LOW will sink current, and can be damaged if the current is not limited to 20ma. In your original diagram the pin was directly connected to a 5v supply.

The diagram is still wrong.

Now would be a good time to look at the Adafruit tutorial.

Best to model the behavior and have a bit of fun before the coding...

$ 1 0.000005 10.20027730826997 50 5 50 5e-11
g 96 384 96 448 0 0
R 96 48 96 16 0 0 40 5 0 0 0.5
374 96 384 96 272 0 0.43570000000000003 Light\sBrightness
w 96 48 96 160 0
r 96 160 96 272 0 10000
w 96 272 208 272 0
p 208 272 288 272 1 0 0
o 6 64 0 4098 5 0.1 0 1

http://falstad.com/circuit/