Instructables

Analog to Digital not correct for set trigger value

I am trying to remedy false hits.
I have a remote operated light that uses a 38MHz 3 leg IR sensor and a  TV remote for on/off, but it can have false hits, IE light may come on when ever. 
I decided it needed a  long button press or in this case a long IR input. Because the IR sensor doesn't go from 0 to 5 volts i have set a threshold of 600. IR voltage values are, low is 1.8v and high is 3.6v. So i decided 2.75V could be a reasonable threshold value. that ROUGHLY translated to 600 if going from 0 to 1023.

This sketch works good for a button but trying to use the IR sensor does not.
I have tried to map the sensor and put a trigger value but something is a miss with my work.
Any suggestions? 

/*
*  Press & Hold Switch LED program
*/

// Parameters
int HOLD_DELAY = 500;    // Sets the hold delay of switch for LED state change

int ledPin     = 9;      // LED is connected to pin x
int switchPin  = A0;      // Switch is connected to pin x
int val = 0;
int statePin = LOW;

int THRESHOLD = 600;

// In-Program Variables
unsigned long start_hold;
boolean allow = false;
int sw_state;
int sw_laststate = LOW;
int led_state = LOW;

// Setup
void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);      // Set the LED pin as output
  pinMode(switchPin, INPUT);    // Set the switch pin as input
}

// Loop
void loop(){
  int val = analogRead(switchPin);
   val = map(val, 0, 1023, 0, 255);
   if (val >= THRESHOLD) {

    statePin = !statePin;
   
    digitalWrite(ledPin, statePin);
    Serial.print(val);
    Serial.println("Triggered!");
    delay(80);
  sw_state = digitalRead(switchPin);             // read input value
 
  if (sw_state == HIGH && sw_laststate == LOW){  // for button pressing
    start_hold = millis();                       // mark the time
    allow = true;                                // allow LED state changes
  }
    
  if (allow == true && sw_state == HIGH && sw_laststate == HIGH){  // if button remains pressed
      if ((millis() - start_hold) >= HOLD_DELAY){                   // for longer than x/1000 sec(s)
         led_state = !led_state;                                   // change state of LED
         allow = false;                                            // prevent multiple state changes
      }
  }

  sw_laststate = sw_state;  
  digitalWrite(ledPin, led_state);


   }
}


 

Who's remote is it ? THere are standard codes, and standard Arduino libraries that can decode them. You need to find a way of detecting legitimate codes to activate the light, not rely on intensity measurement.
WWC (author)  steveastrouk1 year ago
I could use the remote libraries and use a specific button from a specific remote, but that would make it non universal. I was trying to make it so any remote would still be able to operate it.
From the couple of remotes i tried the intensity levels were pretty much all in the same range, so i suspect that would work but the problem is how to apply the threshold correctly.
Make sense?
Its not intensity which is your "problem", what you want to detect it the modulation of the returned signal - you can use the library to say ANYTHING has been received, rather than "specifically" something has been received....

The reason your code isn't working is basically because you are trying to measure a fast AC signal with a slow-ish ADC
WWC (author)  steveastrouk1 year ago
I can have some success if i use the library with out the long button press or button press without the library but combining the two is not playing nice.
I have changed the orders around and renamed  both sketches so they were consistent. i still am missing something, can you see it?

/*
* IRremote: IRrecvDemo - demonstrates receiving IR codes with IRrecv
* An IR detector/demodulator must be connected to the input RECV_PIN.
* Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff
* http://arcfn.com
*/

#include <IRremote.h>
int HOLD_DELAY = 500;
int RECV_PIN = 11;
int RELAY_PIN = 4;

IRrecv irrecv(RECV_PIN);
decode_results results;
unsigned long start_hold;
boolean allow = false;
int sw_state;
int sw_laststate = LOW;
int led_state = LOW;

// Dumps out the decode_results structure.
// Call this after IRrecv::decode()
// void * to work around compiler issue
//void dump(void *v) {
//  decode_results *results = (decode_results *)v
void dump(decode_results *results) {
  int count = results->rawlen;
  if (results->decode_type == UNKNOWN) {
    Serial.println("Could not decode message");
  }
  else {
    if (results->decode_type == NEC) {
      Serial.print("Decoded NEC: ");
    }
    else if (results->decode_type == SONY) {
      Serial.print("Decoded SONY: ");
    }
    else if (results->decode_type == RC5) {
      Serial.print("Decoded RC5: ");
    }
    else if (results->decode_type == RC6) {
      Serial.print("Decoded RC6: ");
    }
    Serial.print(results->value, HEX);
    Serial.print(" (");
    Serial.print(results->bits, DEC);
    Serial.println(" bits)");
  }
  Serial.print("Raw (");
  Serial.print(count, DEC);
  Serial.print("): ");

  for (int i = 0; i < count; i++) {
    if ((i % 2) == 1) {
      Serial.print(results->rawbuf[i]*USECPERTICK, DEC);
    }
    else {
      Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC);
    }
    Serial.print(" ");
  }
  Serial.println("");
}

void setup()
{
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(13, OUTPUT);
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}

int on = 0;
unsigned long last = millis();

void loop() {


  if (irrecv.decode(&results)) {
    // If it's been at least 1/4 second since the last
    // IR received, toggle the relay
    if (millis() - last > 250) {
      on = !on;
      digitalWrite(RELAY_PIN, on ? HIGH : LOW);
      digitalWrite(13, on ? HIGH : LOW);
      dump(&results);
    }
    last = millis();     
    irrecv.resume(); // Receive the next value
  }
  sw_state = digitalRead(RECV_PIN);             // read input value

  if (sw_state == HIGH && sw_laststate == LOW){  // for button pressing
    start_hold = millis();                       // mark the time
    allow = true;                                // allow LED state changes
  }

  if (allow == true && sw_state == HIGH && sw_laststate == HIGH){  // if button remains pressed
    if ((millis() - start_hold) >= HOLD_DELAY){                   // for longer than x/1000 sec(s)
      led_state = !led_state;                                   // change state of LED
      allow = false;                                            // prevent multiple state changes
    }
  }

  sw_laststate = sw_state;  
  digitalWrite(RELAY_PIN, led_state);
}

Does this build for you ? I can't compile it on 1.03
WWC (author)  steveastrouk1 year ago
Yes it does, i am using 1.05
Got it. I can't look at it right now though. I'll put 1.05 on all my systems.

Steve
WWC (author)  steveastrouk1 year ago
I don't get this
There is no ? in Arduino reference.


digitalWrite(RECV_PIN, on ? HIGH : LOW);
digitalWrite(13, on ? HIGH : LOW);
Is it a note to the user in the code ?
This is a pull up/ down on the receiver pin I think
Is this yours ?
sw_laststate = sw_state;
digitalWrite(RECV_PIN, led_state);
WWC (author)  steveastrouk1 year ago
No, came with the package. I had the relay as 11 instead of the correct 4.
Relay and led are responsive to the remote. Will switch on/off or hold on/off.
I have not gotten the delay incorrect.
Not sure what its doing. Its switching a pull up or down ?
WWC (author)  steveastrouk1 year ago
It is switching a pull down from here

I
t works with a push button but an IR sensor just cant give the 0v to 5v a PB can
I put the IR as a direct replacement of the PB. If i could get the IR to give a better 0v to 5v such as a PB probably would work then. I ran the IR signal through a transistor but was unsuccessful with the outcome.  
Ah ! THAT's what's upsetting it then. Just use a separate pin for the button. Otherwise, what's the "resting" state of the receiver pin ? high or low ?

Steve
WWC (author)  steveastrouk1 year ago
I have the PB removed and the IR in its place. The IR goes from 3.25v at rest then to 2.5v when energized. I also just set the switch pin input / low so it would read.
I don't think the arduino pin 11 can recognize the voltage difference enough as it is coded now to change the state of pin 4 relay pin. .
Thats why i was also using the IR library as-well.
I think it needs a pullup resistor.
DigitalWrite (Recv_pin,HIGH);
WWC (author)  steveastrouk1 year ago
Here is my fix:



#define irPin 3 // analog input pin to use as a digital input
#define relayPin 4 // digital output pin for relay

#define debounce 20 // ms debounce period to prevent flickering when IR is switching
#define holdTime 2000 // ms hold period: how long to wait for press+hold event

// Button variables
int irVal = 0; // value read from IR
int irLast = 0; // buffered value of the IR's previous state
long irrDnTime; // time the IR was pressed down
long irrUpTime; // time the IR was released
boolean ignoreUp = false; // whether to ignore the ir release because the click+hold was triggered

boolean relayVal = false; // state of relay

void setup() {

  // Set IR input pin
  pinMode(irPin, INPUT);
  digitalWrite(irPin, HIGH );

  // Set relay output pins
  pinMode(relayPin, OUTPUT);
  digitalWrite(relayPin, relayVal);
}

void loop(){

  // Read the state of the IR
  irVal = digitalRead(irPin);

  // Test for IR pressed and store the down time
  if (irVal == LOW && irLast == HIGH && (millis() - irrUpTime) > long(debounce))
  {
    irrDnTime = millis();
  }

  // Test for IR release and store the up time
  if (irVal == HIGH && irLast == LOW && (millis() - irrDnTime) > long(debounce))

    // Test for IR held down for longer than the hold time
    if (irVal == LOW && (millis() - irrDnTime) > long(holdTime))

      irLast = irVal;
}

void event()
{
  relayVal = !relayVal;
  digitalWrite(relayPin, relayVal);
}

Elegant.
WWC (author)  steveastrouk1 year ago
Bed time in Asia. Tomorrow again.
WWC (author)  steveastrouk1 year ago
I stripped it sown some more. The #13 led will respond to the remote input , the RELAY_PIN will not and the HOLD_DELAY is only along for the ride.
I am still hacking on it. 

 

#include <IRremote.h>
int HOLD_DELAY = 500;
int RECV_PIN = 11;
int RELAY_PIN = 4;

IRrecv irrecv(RECV_PIN);
decode_results results;
unsigned long start_hold;
boolean allow = false;
int sw_state;
int sw_laststate = LOW;
int led_state = LOW;

void setup()
{
  pinMode(RECV_PIN, INPUT);
  pinMode(13, OUTPUT);
  pinMode(RELAY_PIN, OUTPUT);
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}

int on = 0;
unsigned long last = millis();

void loop() {


  if (irrecv.decode(&results)) {
    // If it's been at least 1/4 second since the last
    // IR received, toggle the relay
    if (millis() - last > 250) {
      on = !on;
      digitalWrite(RECV_PIN, on ? HIGH : LOW);
      digitalWrite(13, on ? HIGH : LOW);
      // dump(&results);
    }
    last = millis();     
    irrecv.resume(); // Receive the next value
  }
  sw_state = digitalRead(RECV_PIN);             // read input value

  if (sw_state == HIGH && sw_laststate == LOW){  // for button pressing
    start_hold = millis();                       // mark the time
    allow = true;                                // allow LED state changes
  }

  if (allow == true && sw_state == HIGH && sw_laststate == HIGH){  // if button remains pressed
    if ((millis() - start_hold) >= HOLD_DELAY){                   // for longer than x/1000 sec(s)
      led_state = !led_state;                                   // change state of LED
      allow = false;                                            // prevent multiple state changes
    }
  }

  sw_laststate = sw_state;  
  digitalWrite(RECV_PIN, led_state);
}

WWC (author)  steveastrouk1 year ago
The problem is the cut and past, check your email
WWC (author)  steveastrouk1 year ago
That's why ur da man.
The IR library has a toggle relay with raw codes already.
I will check it out tomorrow.
iceng1 year ago
If you have an iPhone you can view the intensity of IR controllers.

Simply use the facetime camera, as it does not have an IR filter

and will clearly show the infrared LED intensity.
WWC (author)  iceng1 year ago
Thanks for the tip!
MDheliMech1 year ago
I saw in you question you stated "the light may come on whenever." I was wandering if you meant randomly even without an IR source applied, or that any button press would trigger it and you only wanted a certain press? If you are having a false ie. the LED comes on with no button press at all just at random you may have a wiring problem. The first time I used a 3 leg IR sensor I didn't wire it right and ended up with a floating ground. That allowed actual false hits.
WWC (author)  MDheliMech1 year ago
This actually an upgrade/enhancement to an existing project.
The false hits come from stray IR that is everywhere, that's why i planed to add a 2 sec long button press to avoid that problem.
So in this particular instance i can't blame it on wiring.
Pro

Get More Out of Instructables

Already have an Account?

close

PDF Downloads
As a Pro member, you will gain access to download any Instructable in the PDF format. You also have the ability to customize your PDF download.

Upgrade to Pro today!