View Single Post
  #4  
Old 10-17-2018, 03:42 PM
Wombii's Avatar
Wombii Wombii is offline
Green Horn
 
Join Date: Feb 2018
Location: Norway
Posts: 231
Wombii is on a distinguished road
Default Re: Remote LED switching with Arduino examples.

Thank you. The potential is endless and it's not too hard to learn if you find the right resource to learn from. Fortunately there are a lot of people out there writing guides in different ways. I remember learning the syntax felt overwhelming when I first got started, but it soon turned into a challenge learning how to think linearly and take one step at a time.


The reason I wanted to learn about this a decade ago was that I wanted to run multiple light functions and a 3 speed gearbox from a 3 channel radio. Not having enough channels seems like a common problem in this hobby, so let's see if we can build a function that helps with that.


This method can be used to switch gears without a 3 position switch, switch turn signals by flicking the steering wheel twice, controlling all the emergency lights you could want or controlling double-tap style reverse lights.

One way of attacking a problem is with pseudo code. Try refining it until each line only does a single action.
Remember that the program loops about 50 times per second.

This is what we want to happen from a human perspective:

Code:
        click switch x times
        stop clicking for a while
        something happens based on number of clicks
Let's start with figuring out when the human has stopped clicking.
Code:
        if click detected
            remember time of click
            (The saved time is overwritten for every new click detected)

        if time since click > timeout setting
            human stopped clicking!
We should probably count how many times we clicked before the timeout too:
Code:
        if click detected
            remember time of click
            add 1 to click counter

        if time since click > timeout setting
            do something based on number of clicks in the counter
            reset click counter
Expand "do something based on number of clicks in the counter"
Code:
            if click counter is 1
                do action
            if click counter is 2
                do another action
The bigger problem is how to figure out when the human clicks something.
Let's say we have a normal radio with a 2 position switch but no pushbuttons.
Flicking the switch down then back up can be one click:
Code:
        if switch is up
            nothing is happening here
        
        if switch is down
            save last switch position as down

        if switch position was down (and)
            if switch position is now up
              this is a click
Cleaning up and combining we get:
Code:
        if switch is down
            save last switch position as down

        if switch was down AND switch is up
            switch position is no longer down
            remember time of click
            add 1 to click counter

        if time since click > timeout setting
            if click counter is 1
                do action
            if click counter is 2
                do another action
            reset click counter
This can be translated to a language the Arduino understands.

Code:
if (channel1Value < 1300)
{
  switchWasDown = 1;          //last known switch position is down.
}

if ( (switchWasDown == 1) && (channel1Value > 1300) )
{
  switchWasDown = 0;          //switch position is no longer down.
  timeOfLastClick = millis(); //remember time of click
  numberOfClicks++;           //add 1 to the click counter. ++ adds 1 and -- subtracts 1.
}

if (millis() - timeOfLastClick > clickTimeout)
{
  if (numberOfClicks == 1)
  {
    digitalWrite(13,HIGH);
  }
  if (numberOfClicks == 2)
  {
    digitalWrite(13,LOW);
  }
  numberOfClicks = 0;         //reset click counter
}
And a full example based on example 2. Arduino+receiver only. Flick the switch to turn on the onboard LED, flick the switch twice to turn it off. Open serial monitor to see channel pulse value, timeout timer, click counter status and result.
Code:
/************************************************************

For this example you can connect a wire from the signal pin on a channel on your receiver to the A0 pin on your Arduino.
Power the Arduino and receiver however you want, but make sure there is a ground wire between the receiver and Arduino.
The Arduino onboard LED should turn on or off when flipping the switch on your transmitter once or twice.

************************************************************/

//**Give your arduino I/O pins name tags**
// This is completely optional, but makes the program easier to read for humans.
//
// Pins available on most Arduinos. "*" means the pin can be used as a PWM pin for dimming LEDs. A0-A5 can also be called 14-19.
// RX  TX  02  03* 04  05* 06* 07 08  09* 10* 11* 12  13 A0  A1  A2  A3  A4  A5

// LED pin aliases:
const byte LEDpin1 = 13;

// Radio pin aliases:
const byte channel1Pin = A0;

//**set up variables:**
//This is not optional. Variables are little boxes to store numbers in.

//Radio channel variables:
int channel1Value = 1500; //1.5ms (center) as a default value.

//Variables for the clicking part
int clickTimeout = 1000;            //Wait 1000 milliseconds after the last click. int can hold large values.
byte switchWasDown = 0;             //We need a variable to remember switch position. byte is enough to hold a value of 0-255.
unsigned long timeOfLastClick = 0;  //and a variable to remember the time of the last click. unsigned long is huge and can hold the current time.
byte numberOfClicks = 0;            //and a variable to count the number of clicks. byte is enough to hold a value of 0-255.



//This runs once at power on.
void setup()
{
    //set LEDpins to switch mode (output +5v or 0v)
    pinMode(13,OUTPUT);

    //Open the Serial port to enable sending data to the Arduino serial monitor or serial plotter.
    Serial.begin(115200);

}

//This keeps looping.
void loop()
{

    // --- Read channels --- 

    //This is the easiest way to read channels, but it's slow for more than 2 channels.
    //(One loop will take minimum 10ms, possibly 60+ms with 3 channels depending on receiver and the order you plug the channels in.)
        channel1Value = pulseIn(channel1Pin,HIGH);

    //Optional: Send pulselength of channel 1 to the Arduino serial monitor or serial plotter (115200 baud rate)
        Serial.print(channel1Value);
        Serial.print('\t');


    // --- clicking example --- 

        if (channel1Value < 1300)
        {
          switchWasDown = 1;          //last known switch position is down.
        }

        if ( (switchWasDown == 1) && (channel1Value > 1300) )
        {
          switchWasDown = 0;          //switch position is no longer down.
          timeOfLastClick = millis(); //remember time of click
          numberOfClicks++;           //add 1 to the click counter. ++ adds 1 and -- subtracts 1.
        }

        Serial.print("Timeout:");
        Serial.print(millis() - timeOfLastClick);
        Serial.print('\t');

        if (millis() - timeOfLastClick > clickTimeout)
        {
          if (numberOfClicks == 1)
          {
            digitalWrite(13,HIGH);
            Serial.println("Detected 1 click");
          }
          if (numberOfClicks == 2)
          {
            digitalWrite(13,LOW);
            Serial.println("Detected 2 clicks");
          }
          if (numberOfClicks > 2)
          {
            Serial.println("Detected many clicks");
          }
          numberOfClicks = 0;         //reset click counter
        }

        Serial.print("Current click count:");
        Serial.println(numberOfClicks);
    

    
} //End of loop
Reply With Quote