RC Truck and Construction  

Go Back   RC Truck and Construction > RC Tech section. > Electronics tech

Electronics tech Anything to do with the electronics in a model. Lights, Radio, ESC, Servo, Basic electrical.


Reply
 
Thread Tools Display Modes
  #1  
Old 10-13-2018, 11:00 AM
Wombii's Avatar
Wombii Wombii is offline
Green Horn
 
Join Date: Feb 2018
Location: Norway
Posts: 231
Wombii is on a distinguished road
Default Remote LED switching with Arduino examples.

I hope to one day write some getting started tutorials with Arduinos and RC, but for now, here are some example programs. You should already be comfortable with basic DC electronic circuits (don't short circuit or fry stuff) and very basic Arduino operations before starting here.

An Arduino nano is a nice cheap device (around 4 USD for Chinese clones) with 17 digital I/O pins. Each pin can be switched between 0v and 5v or be used to sense 0 or 5 volts in input mode. 5 of the pins can also be used as analog voltage sensors. Some of the pins can be switched with pwm, allowing you to dim an LED.

You can try switching LEDs directly (remember resistors) as long as you keep below 20mA per pin and 200 mA in total. This is fine for a simple flashing circuit, but for more high power demands you will probably want to use transistors. Look into the ULN2003 transistor array to avoid having to calculate transistor base resistors (you'll still need LED resistors though).

All Arduinos have an onboard LED that can be used for testing purposes on pin 13.


The Arduino +5v pin can supply the Arduino with power or supply other devices if the Arduino is powered from another source. Don't supply your Arduino from a 5v source like a BEC through the +5v pin while at the same time having it connected to USB. This will be like connecting the BEC directly to your PC's USB port. Think about your connections before connecting power or things will start smoking.

You can however safely power the Arduino from a source on VIN or dc jack while connected to USB as the Arduino will automatically connect its 5v rail to the higher source.


Example 1: Switch onboard LED from RC transmitter and send the RC channel pulse length to a PC serial monitor to see how things work.
In this example you can power the receiver from the Arduino +5v pin while the Arduino is connected to USB as long as you don't connect anything else to the receiver. Connect a wire from one of the signal pins on the receiver to pin A0 on the Arduino. It's a very short program, most of it is just comments for humans. This is enough to make brake lights or reverse lights.


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 (and flash) or off when flipping the switch on your transmitter.

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

/*
read channels
simple switching and output
*/


//**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

// 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.




//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.println(channel1Value);


    // --- Convert channel values to logical switches --- 

    //Channel1 with 2 positions
        if (channel1Value < 1300)   //if the pulselength of channel 1 is less than 1300 microseconds
        {
            //The switch is off
            digitalWrite(13,LOW);     //turn the onboard LED on pin 13 off.
        }
        else                        //if the pulselength is more than 1300 microseconds
        {
            //The switch is on
            digitalWrite(13,HIGH);    //turn the onboard LED on pin 13 on.
        }

    
} //End of loop


Example 2: Same setup as example 1, but slightly more advanced. Now we flash the LED when it's turned on. The program is a bit more split up into modules to make it easier to add more functions for the next step. This could be a basic way of making simple turn signals or emergency flashers.

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.

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

/*
read channels
simple switching and output
*/


//**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.

//Light function switch flags:
byte lightFunction1Switch = 0; //off as default value.

//Make variables for LEDpins:
byte LEDpin1State = 0; //defaults to off



//This runs once at power on.
void setup()
{
    //set LEDpins to switch mode (output +5v or 0v)
    pinMode(LEDpin1,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');


    // --- Convert channel values to logical switches --- 

    //Channel1 with 2 positions
        if (channel1Value < 1300)   //if the pulselength of channel 1 is less than 1300 microseconds
        {
            //The switch is off
            lightFunction1Switch = 0;
        }
        else                        //if the pulselength is more than 1300 microseconds
        {
            //The switch is on
            lightFunction1Switch = 1;
        }

    // --- Logic stuff for the switches. ---
    // Note that this part doesn't actually write to the ports, but determines what should be written to the ports.

        //Light function 1 is a simple on/off switch for flasher.

        static unsigned long LEDpin1Time = 0; //Make a variable to store timing value for pin 3. 

        if (lightFunction1Switch == 1) //if switch is on
        {
            //Make light function 1 flash LEDpin1 on/off
            if (millis() - LEDpin1Time > 200) //If [current time] - [last time pin1 switched] is more than 200 ms
            {
                LEDpin1State = !LEDpin1State; //! means NOT or opposite. Set state LOW if it's HIGH and vice versa.
                LEDpin1Time = millis(); //store [current time] as [last time pin1 switched].
            }

        }
        else //if switch is off
        {
            //Turn LEDpin1 off
            LEDpin1State = 0;
        }

    /// --- Switch the Arduino I/O pins ---
    // digitalWrite(pin,state) where state can be HIGH/LOW or a value. 0 means LOW and anything else means HIGH.
    // analogWrite(pin,value) where value is a value between 0 and 255 can be used to PWM dim an LED on certain pins.

    digitalWrite(LEDpin1,LEDpin1State);


    //This section will send the current state of the LED pins to the "serial monitor" in the Arduino IDE.
    Serial.println(LEDpin1State);
    

    
} //End of loop
Reply With Quote
  #2  
Old 10-13-2018, 11:20 AM
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.

Example 3: If you've made it here, please don't be intimidated. This is the same as example 2, but with 2 extra functions. 1 is a simple on/off. 2 is a simple flash/off. Function 3 is the fun one with a 3 position switch.
Position 1: marker.
Position 2: marker + headlights.
Position 3: marker + wig wag flashing headlights.

Hopefully with some tinkering, you can see how these functions can form the basics of a light kit.

Here you need to connect 3 channels from the receiver to the Arduino pins A0, A1, A2. You'll also need LEDs connected from pins 2, 3, 4, 5, 6 with appropriate resistors to GND. 1000 ohm should work fine for bright blues without blinding you or smoking anything.
You can also skip the LEDs and just watch the Serial monitor output.

Note that this setup is only for testing. If you connect anything else to this circuit like a servo, more LEDs or power the receiver from a battery or BEC, make sure you understand how much power goes where, and remove the wire from receiver to the +5v pin on the Arduino when connecting it to USB.

Code:
//Wombii 2018
/*
read channels
simple switching
simple flash timing
output
*/


/***********************************************************************
* If you're comfortable with arrays and for loops:
*   Replace the individual assignments of pin names with an array:

const byte LEDpin[6] = {2,3,4,5,6,7};

*   Replace LEDpin state variables with an array:

byte LEDstate[6] = {0,0,0,0,0,0};

*   Use a for loop to set pinModes:

for(int i=0; i<sizeof(LEDpin) ; i++)
{
    pinMode(LEDstate[i],OUTPUT);
}

*   Use a for loop to switch I/O pins:

for(int i=0; i<sizeof(LEDstate) ; i++)
{
    digitalWrite(LEDpin[i],LEDstate[i]);
}

*   Use array position to read or write a variable:

LEDstate[2] = 1; instead of LEDpin2State = 1:

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


//**map your Arduino output pins to alias names:**
// This is completely optional, but makes the program easier to read for humans.
// I'm using generic terms like LEDpin1 here, but you could replace that with specifics like headlight or turnSignal.
// Just remember to use the same name in the whole program, and you should probably rename the variables too.
//
// 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

const byte LEDpin1 = 2;
const byte LEDpin2 = 3;
const byte LEDpin3 = 4;
const byte LEDpin4 = 5;
const byte LEDpin5 = 6;
const byte LEDpin6 = 7;

// Radio pin aliases:
const byte channel1Pin = A0;
const byte channel2Pin = A1;
const byte channel3Pin = A2;



//**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.
int channel2Value = 1500;
int channel3Value = 1500;

//Light function switch flags:
byte lightFunction1Switch = 0; //off as default value.
byte lightFunction2Switch = 0;
byte lightFunction3Switch = 0;

//Make variables for LEDpins:
byte LEDpin1State = 0; //defaults to off
byte LEDpin2State = 0; //defaults to off
byte LEDpin3State = 0; //defaults to off
byte LEDpin4State = 0; //defaults to off
byte LEDpin5State = 0; //defaults to off
byte LEDpin6State = 0; //defaults to off







//This runs once at power on.
void setup()
{
    //set LEDpins to switch mode HIGH/LOW
    pinMode(LEDpin1,OUTPUT);
    pinMode(LEDpin2,OUTPUT);
    pinMode(LEDpin3,OUTPUT);
    pinMode(LEDpin4,OUTPUT);
    pinMode(LEDpin5,OUTPUT);
    pinMode(LEDpin6,OUTPUT);
    
    //all pins default to LOW, set HIGH if necessary:
    digitalWrite(LEDpin1,LEDpin1State);
    digitalWrite(LEDpin2,LEDpin2State);
    digitalWrite(LEDpin3,LEDpin3State);
    digitalWrite(LEDpin4,LEDpin4State);
    digitalWrite(LEDpin5,LEDpin5State);
    digitalWrite(LEDpin6,LEDpin6State);

    //Start the serial port to enable serial communication with a pc.
    Serial.begin(115200);

}

//This keeps looping.
void loop()
{

    // --- Read channels --- 

    //This is the easiest way to read channels, but it's slow and prone to failure 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);
        channel2Value = pulseIn(channel2Pin,HIGH);
        channel3Value = pulseIn(channel3Pin,HIGH);

        //Send info to a pc to test the receiver connection. Open "serial plotter" in the Arduino IDE and select 115200 as baud rate.
        //The received channel pulse lengths should show up in a nice chart.

        Serial.print(channel1Value);
        Serial.print('\t');
        Serial.print(channel2Value);
        Serial.print('\t');
        Serial.print(channel3Value);
        Serial.print('\t');

    // --- Convert channel values to logical switches --- 
    // Channel values should come in as a value in the range of 800-2200 with center value of 1500 microseconds.
    // This part could be skipped, but makes it easier to troubleshoot.

    //Channel1 with 2 positions
        if (channel1Value < 1300)
        {
            //The switch is off
            lightFunction1Switch = 0;
        }
        else
        {
            //The switch is on
            lightFunction1Switch = 1;
        }

    //Channel2 with 2 positions
        if (channel2Value < 1300)
        {
            //The switch is off
            lightFunction2Switch = 0;
        }
        else
        {
            //The switch is on
            lightFunction2Switch = 1;
        }
    
    //Channel3 with 3 positions: ( <1300, 1300-1700, 1700> )
        if (channel3Value < 1300)
        {
            //The switch is bottom
            lightFunction3Switch = 0;
        }
        else if (channel3Value > 1700)
        {
            //The switch is top
            lightFunction3Switch = 2;
        }
        else
        {
            //The switch is middle
            lightFunction3Switch = 1;
        }

    


    // --- Logic stuff for the switches. ---
    // Note that this part doesn't actually write to the ports, but determines what should be written to the ports.

        //Light function 1 is a simple on/off switch.
        if (lightFunction1Switch == 1)
        {
            //Turn on LEDpin 1 and 2
            LEDpin1State = 1;
            LEDpin2State = 1;
        }
        else
        {
            //Turn off LEDpin 1 and 2
            LEDpin1State = 0;
            LEDpin2State = 0;
        }


        //Light function 2 is a simple on/off switch for flasher.

        static unsigned long LEDpin3Time = 0; //Make a variable to store timing value for pin 3. 

        if (lightFunction2Switch == 1) //if switch is on
        {
            //Make light function 2 flash LEDpin3 on/off
            if (millis() - LEDpin3Time > 200) //If [current time] - [last time pin1 switched] is more than 200 ms
            {
                LEDpin3State = !LEDpin3State; //! means NOT or opposite. Set state LOW if it's HIGH and vice versa.
                LEDpin3Time = millis(); //store [current time] as [last time pin1 switched].
            }

        }
        else //if switch is off
        {
            //Turn LEDpin3 off
            LEDpin3State = 0;
        }


        //Light function 3: 0 = marker on, headlight off / 1 = marker + headlights on / 2 = marker + wig wag flash headlights
        
        static unsigned long LEDpin5Time = 0; //Make a variable to store timing value for pin 5

        if (lightFunction3Switch == 2) //if switch is on
        {
            LEDpin4State = 1;
            //Flash LEDpin5 on/off
            if (millis() - LEDpin5Time > 150) //If [current time] - [last time pin1 switched] is more than 200 ms
            {
                LEDpin5State = !LEDpin5State; //! means NOT or opposite. Set state LOW if it's HIGH and vice versa.
                LEDpin5Time = millis(); //store [current time] as [last time pin1 switched].
            }
            
            LEDpin6State = !LEDpin5State; //pin 6 should be the opposite state of pin 5.

        }
        else if (lightFunction3Switch == 1)
        {
            //Turn pin 4,5,6 on
            LEDpin4State = 1;
            LEDpin5State = 1;
            LEDpin6State = 1;
        }
        else //if switch is off
        {
            //Turn pin 4 on, 5 and 6 off.
            LEDpin4State = 1;
            LEDpin5State = 0;
            LEDpin6State = 0;
        }

    
    /// --- Switch the Arduino I/O pins ---
    // digitalWrite(pin,state) where state can be HIGH/LOW or a value. 0 means LOW and anything else means HIGH.
    // analogWrite(pin,value) where value is a value between 0 and 255 can be used to PWM dim an LED on certain pins.

    digitalWrite(LEDpin1,LEDpin1State);
    digitalWrite(LEDpin2,LEDpin2State);
    digitalWrite(LEDpin3,LEDpin3State);
    digitalWrite(LEDpin4,LEDpin4State);
    digitalWrite(LEDpin5,LEDpin5State);
    digitalWrite(LEDpin6,LEDpin6State);

    
    //This section will send the current state of the LED pins to the "serial monitor" in the Arduino IDE.
    Serial.print(LEDpin1State);
    Serial.print('\t');
    Serial.print(LEDpin2State);
    Serial.print('\t');
    Serial.print(LEDpin3State);
    Serial.print('\t');
    Serial.print(LEDpin4State);
    Serial.print('\t');
    Serial.print(LEDpin5State);
    Serial.print('\t');
    Serial.println(LEDpin6State);
    //*/

    
} //End of loop
Reply With Quote
  #3  
Old 10-13-2018, 08:06 PM
Zabco Zabco is offline
Green Horn
 
Join Date: Sep 2016
Location: Ohio
Posts: 253
Zabco is on a distinguished road
Default Re: Remote LED switching with Arduino examples.

Very nice start on a arduino tutorial Wombii. I've been wanting to learn more about the potential use of these boards in our hobby and I look forward to seeing more from you on the subject. Thanks.
Reply With Quote
  #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
  #5  
Old 10-17-2018, 09:54 PM
frizzen's Avatar
frizzen frizzen is offline
Big Dawg On The Bone
 
Join Date: Jan 2016
Location: indy, indiana
Posts: 2,040
frizzen is on a distinguished road
Default Re: Remote LED switching with Arduino examples.

Very cool.

How about some for what's needed to get started? Components, interface cables, and that kind of stuff

(Taking notes from the back of the class)
__________________
What do ya mean "Cars are neither Trucks or Construction"?
It's still scale, and i play fairly well with others, most of the time...
Reply With Quote
  #6  
Old 10-18-2018, 09:51 AM
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.

I'll give it a shot Hopefully it won't be a complete formatting mess.

Strictly speaking, what you need to get started with an Arduino is the Arduino itself, a USB cable and install the free software on your pc. I recommend getting a genuine Arduino UNO / Genuino UNO to start with, as the cheap ebay ones have a higher dead on arrival rate, and it will help support the development of the software and hardware financially. When you've got the basics down, buy a drawer full of small Arduino nanos from China like me.

If you're using windows 10 you can go to the windows store app and search for "Arduino IDE" https://www.microsoft.com/store/productId/9NBLGGH4RSD8 . Installing from the store will keep the app updated. Other install instructions can be found here: https://www.arduino.cc/en/Guide/HomePage .

Here are instructions for uploading the first sketch to an Arduino UNO: https://www.arduino.cc/en/Guide/ArduinoUno

And here are instructions for uploading the first sketch to an Arduino Nano: https://www.arduino.cc/en/Guide/ArduinoNano . If you bought cheap off brand nanos, you may have to select Atmega328p (Old bootloader) in the processor menu to get it to upload and you may have to install some drivers for the USB chip.

After getting the first blink example to work, look through the other examples and keep https://www.arduino.cc/reference/en/ close by. That will be your favorite site for a while.

***
For the people towards the front of the class:
If you have any experience with C or C++, you may notice that you feel right at home. The basic Arduino is an Atmega 328p microcontroller and a USB-serial converter on a pcb. If you want to use AVR C examples from Atmega or school, with int main() instead of setup() and loop() or PIND instead of digitalRead(), those can usually be pasted right into the Arduino environment. Arduino just adds some premade functions and clock setups behind the scenes to simplify the coding.
***



There are many getting started kits out there, but I would recommend getting the following as a minimum, in a prioritised list (The links to banggood.com are only meant as examples):
- Breadboard, just push the components in and make your circuit. https://www.banggood.com/Prototype-B...-p-948106.html
- Dupont jumper wires, can be used with breadboard and arduino or you can even plug LEDs straight into them. Get all three types, female-female, male-male, male-female. https://www.banggood.com/120pcs-20cm...-p-974006.html
- An assortment of resistors. The blue 1/4 watt 1% is very cheap, but the leads are a bit thin. https://www.banggood.com/Wholesale-6...e-p-53320.html
- LEDs. Standard 5mm of any color will do. https://www.banggood.com/375pcs-3MM-...p-1027601.html
- Pushbuttons. Often called "PCB tactile push button". Make sure they have legs. https://www.banggood.com/100pcs-Mini...-p-917570.html

- Digital multimeter. Being able to measure voltage and resistance will help you a lot. You probably don't need to go expensive for 5 volt electronics.

- 22-24 AWG solid core wire to make your own smaller jumper wires for the breadboard
- Wire strippers
- Wire cutters

Some programming tips:

Looking at https://www.arduino.cc/reference/en/ you may feel a bit overwhelmed. Remember that all those functions are there to help you! You don't need to learn all of them. Here are some info on the basics:

The first thing that confused me was whitespace. Whitespace like spaces and indents and linebreaks doesn't matter, they're just there to make it look prettier. The only time a line break matters is to end a //comment.

FALSE and LOW is the same as 0. TRUE and HIGH is the same as anything else. This works for both tests and I/O functions.

A variable is a box to store numbers in. You can make them the size you want and call them (almost) whatever you like.
Byte is a 1 byte variable, storing a value up to 255 when you want to save memory. Int will be your standard workhorse, 2 bytes stores up to 32768. Long stores 4 bytes for a value of 2 billion.
Variable1 = 23; saves the value 23 in the variable Variable1.
Variable1 = Variable1 - 3; Makes the saved value 20.

There are two basic control statements: if…else and while. Switch…case is series of if…else statements and for can be done with a while loop.
If ( thing1 > thing2 )
{
thing3 = 76;
}
If the test condition inside the parenthesis is true or is more than 0, the instructions inside the curly brackets are performed. The test conditions can be math, a single variable or a test like <, >, == (is equal to), != (not equal to), >= (larger or equal) and <= (smaller or equal) with multiple variables or values.

Else if( thing1 == thing2 )
{
thing3 = 77;
}
Else
{
thing3 = 78;
}

Else if and else are optional and will immediately follow the if statement. Else will do its thing if the other test conditions are false or 0.

While( thing1 > thing2 )
{
Helpimstuckinaloop = 1;
}

While will loop inside the curly brackets as long as the test condition is true or more than 0.

counter = 10;
While ( counter > 0 )
{
delay(1000);
counter = counter - 1;
}

This is a more useful while loop that can be replaced with a "for" statement. This example will delay for 10 x 1000 milliseconds.

Sometimes you'll see these control statements without curly brackets. The curly brackets are optional if there is only one single instruction in the branch, but skipping them can cause human confusion.

Digital in and out:
The I/O pins can be internally switched to 0v (LOW) or 5v (HIGH). They can also be disconnected or floating. The behaviour is switched with pinMode() and digitalWrite(). digitalRead() can read the state of the pin.


pinMode(pin number, mode);
All pins default to INPUT and LOW if not changed.
- Forgetting to set pin mode to OUTPUT is a common error if an LED is less bright than expected.
mode OUTPUT:
Use a series resistor for all connections when setting pin mode to OUTPUT.

digitalWrite(pin number, LOW):
The pin is connected internally to 0v.



digitalWrite(pin number, HIGH);
The pin is connected internally to 5v.
Do not connect to anything higher than 5v.
Do not connect directly to ground.

mode INPUT:


digitalWrite(pin number, LOW):
The pin is in high-impedance mode and will not affect the external circuit it's connected to. The external circuit will see it as if it was disconnected.
Usually used with an external pull up or pull down resistor when using digitalRead() or the state may float and be undefined.




digitalWrite(pin number, HIGH);
The pin is connected internally to 5v through a pull up resistor.
Allows connecting a switch between pin and ground without an extra pull up resistor, but be careful to not accidentally switch pin mode to OUTPUT or the 5v rail could be shorted to ground, destroying the pin.


* mode INPUT_PULLUP:

INPUT_PULLUP is a shortcut for setting pin mode INPUT and digitalWrite HIGH.
Reply With Quote
  #7  
Old 06-17-2019, 03:55 PM
quart quart is offline
Newbie
 
Join Date: May 2013
Posts: 3
quart is on a distinguished road
Default Re: Remote LED switching with Arduino examples.

Thanks for very good information and code.
I am new to Arduino but done some other programming with HTML and PHP.
Think I got everything working, but now I want to add my throttle channel from the radio and use it for reversing lights?
Can someone help with a piece of code for when channelX goes below YY value it turn on LEDpinZZ

Last edited by quart; 06-17-2019 at 04:39 PM.
Reply With Quote
  #8  
Old 06-24-2019, 09:05 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.

We can absolutely get that working! Did you test the first example in the first post? That example should turn on the onboard LED at pin 13 when the channel goes below 1300 us. You can change that to 1500 for a standard center value or change < to > if the throttle channel is reversed. You can also use the serial monitor with that example to read out what the program registers as the channel value at any time to find your specific center.
If that does what you want, that's great. If you want it to also understand the difference between braking and reverse we need to complicate things. If this is not what you were asking for, let me know
Reply With Quote
  #9  
Old 06-25-2019, 02:13 AM
quart quart is offline
Newbie
 
Join Date: May 2013
Posts: 3
quart is on a distinguished road
Default Re: Remote LED switching with Arduino examples.

I have put a couple of hours into this and now got everything working.
Even extended with reverse sound and light.. Beeping when reversing.
Reply With Quote
  #10  
Old 06-25-2019, 03:17 AM
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.

That's great! Sorry for missing your post all last week.

Here's the relevant parts of my program that estimates when the ESC is in brake or reverse mode. Can be configured to work for double pump reverse or delayed reverse depending on the type of ESC.

Code:
// - Global variables - 
//How your hardware is set up:
const byte throttleAxisReversed = 0;        //Is the throttle channel reversed?
const byte reverseType2 = 0;                //Reverse type: 0 for double pump, 1 for delayed.
const int reverseDelayTicks = 100;          //Delay length for delayed reverse. (20ms*100= 2 sec)

//Throttle channel deadband:
const int throttleNeutralLowerLimit = 1480; //Center - 20
const int throttleNeutralUpperLimit = 1520; //Center + 20

//Light variables:
byte brakeLight = 0;                  //This stores the state of the brake lights.
byte reverseLight = 0;                //This stores the state of the reverse lights.


// - for the loop(): - 
// ---- SETTING FLAGS ---- //
    // ----------------------- //

    //Read throttleAxis and set flags. Also check flag for reversed throttle channel.
    // |  brake    | neutral | forward
    // | reverse   |
    //-------------------------------------------------------------------------------
    byte forwardFlag = 0, brakeFlag = 0, reverseFlag = 0, neutralFlag = 0; 


    if (throttleAxisReversed)
    {
        if (throttleAxis < throttleNeutralLowerLimit)
        forwardFlag = 1;
        
        else if (throttleAxis > throttleNeutralUpperLimit){
        brakeFlag = 1;
        reverseFlag = 1;
        }  
        
        else //if (throttleAxis < throttleNeutralUpperLimit && throttleAxis > throttleNeutralLowerLimit)
        neutralFlag = 1;

    }
    else //if not reversed
    {
        if (throttleAxis > throttleNeutralUpperLimit)
        forwardFlag = 1;
        

        else if (throttleAxis < throttleNeutralLowerLimit){
        brakeFlag = 1;
        reverseFlag = 1; 
        } 
        
        else //if (throttleAxis < throttleNeutralUpperLimit && throttleAxis > throttleNeutralLowerLimit)
        neutralFlag = 1;
    }


// --- USING FLAGS --- //
    // ------------------- //

    //Enable or disable reverselights and brakelights based on axis flags.
    //--------------------------------------------------------------------
    if (forwardFlag){
    reverseLight = 0;
    brakeLight = 0;}

    if (neutralFlag){
    brakeLight = 0;}

    if (brakeFlag)
    brakeLight = 1;

    //Reverse logic
    //-------------------------------
    static byte reverseFlag2 = 0;
    
    //Double pump reverse
    if (reverseType2){
        static byte reverseFlagCount = 0;
        static byte lastWasReverseFlag = 0;
        if (reverseFlag)// && !lastReverseFlag)
        {
            if (lastWasReverseFlag == 0){
            reverseFlagCount++;
            lastWasReverseFlag =1;
            }
        }
        else // if reverseflag == 0
            lastWasReverseFlag = 0;
        if (forwardFlag)
            reverseFlagCount = 0;
        if (reverseFlagCount >= 2){
            //Serial.println("rev");
            reverseFlagCount = 2; //prevent overflow
            reverseLight = 1;
            brakeLight = 0;
            
        }
    }

    //Delayed reverse
    else
    {   
        static byte reverseFlagCount = 0;
        if (reverseFlag)
        {
            reverseFlagCount++;
            if (reverseFlagCount > reverseDelayTicks){
                reverseLight = 1;
                brakeLight = 0;
                reverseFlagCount = reverseDelayTicks; //prevent overflow
                }
        }
        else
        {
            reverseFlagCount = 0;
            reverseLight = 0;
        }
    } 


   // Now we should have these correctly set:
   // brakeLight
   // reverseLight
   // Can be used like: digitalWrite(13,brakeLight);

Last edited by Wombii; 06-25-2019 at 03:20 AM.
Reply With Quote
  #11  
Old 12-18-2019, 05:04 PM
ddmckee54 ddmckee54 is offline
Green Horn
 
Join Date: Dec 2011
Posts: 269
ddmckee54 is on a distinguished road
Default Re: Remote LED switching with Arduino examples.

Just stumbled across this thread. For the last couple of weeks I've been working on programming an Arduino Nano to do something similar. I'm working on an R/C conversion of a Bruder Manitou 2150, with a few compromises and an Arduino I think I can get the job done with 6 channels. I'm going to have to study your programming and see what ideas I can shamelessly borrow.

Don
Reply With Quote
  #12  
Old 12-18-2019, 09:44 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.

That sounds fun! Good luck, and let me know if there's anything I can help with.
Reply With Quote
  #13  
Old 12-19-2019, 04:44 PM
ddmckee54 ddmckee54 is offline
Green Horn
 
Join Date: Dec 2011
Posts: 269
ddmckee54 is on a distinguished road
Default Re: Remote LED switching with Arduino examples.

Wombii:

My plan was to monitor the steering and throttle/direction channels with the Nano. From the pulse widths of those two channels I was going to decode the various LED functions that I wanted to use.

These are the various lights that the Nano will control on my Manitou without using any additional channels:
Headlights/tail-lights - If we're moving turn these on.
Work-lights - If we're not moving, or just moving slowly turn on the work lights.
Back-up lights - If we're in reverse, pulse length less than 1.5 milli-seconds, turn on the back-up lights.
Front Turn signals - If we're turning the appropriate front turn signal will flash on for 250 milli-seconds and then off for 750 milli-seconds.
Rear Turn signals - These do double duty as turn signals and brake lights. If we're turning and not braking they flash in sync with the front turn signals. If we're turning and braking then they are off when the front turn signal is on and vice-versa.
Brake lights - When the average of the speed set-point is decreased, then we're braking - turn on the brake lights for a few seconds.

I've got a timing glitch in the rear turn signal programming and it doesn't always do what I want it to, but I'll find the little bugger and fix it.

I haven't got the R/C channel decoding logic written yet. I was going to use the pulsein function, but everything I've read says that I should be using interrupts instead. I need to look into interrupts and then get the R/C decoding logic written next.

Don

Last edited by ddmckee54; 12-19-2019 at 05:13 PM.
Reply With Quote
  #14  
Old 12-23-2019, 09:35 AM
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.

Sorry, I didn't see your last post until today.
That's a great project to work with the arduino. Seemingly simple on the surface, but can be made terribly complex as you work to perfect each function.

Post #4 above contains an example that could be used to switch turn signals or work lights by flicking the steering a number of times left or right.

I'd say that unless you run into timing critical things that absolutely can not hang or crash, and are reading 3 channels or less, just go with pulseIn. For a lightkit you probably don't need to do stuff anyway without having got an update on the RC channel data.
You just need to be aware that the pulseIn way may in the worst case scenario need 2 frame times (5/11/16.5/20 ms) to read each channel depending on the order the receiver outputs them. If your receiver updates each channel every 20ms, you might for example read throttle pulse, miss steering pulse, wait 20ms for the next steering pulse, then the same for channel 3, meaning your arduino program only loops every 60ms instead of 20. If this gives you an issue, I have made a bit of code that always reads 3 channels in one cycle but sacrifices a bit of accuracy. Another option is to only read one channel in each loop.
If you want to read more than 3 channels with pulseIn or the looptimes end up longer than your light flashing intervals, you can probably work around most issues by changing the order you're reading the channels in. (One of my receivers output ch1 and ch2 at the same time before ch3, so reading ch1-ch3-ch2 instead of ch1-ch2-ch3 saved me 20 ms).

For my fire truck project I'm using the SBUS protocol to read 16 channels.

You may want to have a look at Open Source Lights, an arduino based light controller. I don't use it personally as I started my project long before I found it, but it's very good (though complex to read through because of all the configuration options). I tried to help by contributing my light flashing+fading code in version 3, but some people have had problems with it, so you might want to look at version 2. It uses pulseIn, but with some error checking. V3 reads only one channel per loop to make sure it gets a stable loop time, because it uses loop counts instead of millis() to flash the lights.
Reply With Quote
  #15  
Old 01-16-2020, 05:09 PM
ddmckee54 ddmckee54 is offline
Green Horn
 
Join Date: Dec 2011
Posts: 269
ddmckee54 is on a distinguished road
Default Re: Remote LED switching with Arduino examples.

Wombii:

The delay is OK. My day job is in engineering so the Christmas and July 4th plant shutdowns are my busiest times of the year. This is the first time I've been able to get back to this. I've talked to a member of another forum and he gave me a lot of info regarding interrupts. Because of him I found the FAST SERVO library which has a TON of good stuff in it. Hopefully I can get back to this in another couple of weeks and make some more progress.

Don
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 08:30 PM.


Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.