2014-12-19 08:45:50 -08:00
/*
This sketch demonstrates how to use < SoftRcPulseIn > library to get RC pulses from a receiver and to use < SoftRcPulseOut > library to drive 2 servos .
The first servo will follow the order , and the second one will have a reverted motion .
Please notice this sketch is fully asynchronous : no blocking functions such as delay ( ) or pulseIn ( ) are used .
Tested on arduino UNO , ATtiny84 , ATtiny85 and Digispark rev2 ( Model A ) .
RC Navy 2013
http : //p.loussouarn.free.fr
*/
# include <SoftRcPulseIn.h>
# include <SoftRcPulseOut.h>
# include <TinyPinChange.h> /* Needed for <SoftRcPulseIn> library */
# define RX_CHANNEL_PIN 2
# define SERVO1_PIN 3
# define SERVO2_PIN 4
# define LED_PIN 1 //1 on Digispark rev2 (Model A), change to pin 0 for Digispark rev1 (Model B), change to 13 for UNO
# define LED_HALF_PERIOD_MS 250
# define PULSE_MAX_PERIOD_MS 30 /* To refresh the servo in case of pulse extinction */
# define NOW 1
# define NEUTRAL_US 1500 /* Default position in case of no pulse at startup */
enum { NORMAL = 0 , INVERTED , SERVO_NB } ; /* Trick: use an enumeration to declare the index of the servos AND the amount of servos */
SoftRcPulseIn RxChannelPulse ; /* RxChannelPulse is an objet of SoftRcPulseIn type */
SoftRcPulseOut ServoMotor [ SERVO_NB ] ; /* Table Creation for 2 objets of SoftRcPulseOut type */
/* Possible values to compute a shifting average fin order to smooth the recieved pulse witdh */
# define AVG_WITH_1_VALUE 0
# define AVG_WITH_2_VALUES 1
# define AVG_WITH_4_VALUES 2
# define AVG_WITH_8_VALUES 3
# define AVG_WITH_16_VALUES 4
# define AVERAGE_LEVEL AVG_WITH_4_VALUES /* Choose here the average level among the above listed values */
/* Higher is the average level, more the system is stable (jitter suppression), but lesser is the reaction */
/* Macro for average */
# define AVERAGE(ValueToAverage,LastReceivedValue,AverageLevelInPowerOf2) ValueToAverage=(((ValueToAverage)*((1<<(AverageLevelInPowerOf2))-1)+(LastReceivedValue)) / (1<<(AverageLevelInPowerOf2)))
/* Variables */
uint32_t LedStartMs = millis ( ) ;
uint32_t RxPulseStartMs = millis ( ) ;
boolean LedState = HIGH ;
void setup ( )
{
2015-01-14 18:08:45 -08:00
# if !defined(__AVR_ATtiny24__) && !defined(__AVR_ATtiny44__) && !defined(__AVR_ATtiny84__) && !defined(__AVR_ATtiny25__) && !defined(__AVR_ATtiny45__) && !defined(__AVR_ATtiny85__) && !defined(__AVR_ATtiny167__)
2014-12-19 08:45:50 -08:00
Serial . begin ( 9600 ) ;
Serial . print ( " SoftRcPulseIn library V " ) ; Serial . print ( SoftRcPulseIn : : LibTextVersionRevision ( ) ) ; Serial . print ( " demo " ) ; /* For arduino UNO which has an hardware UART, display the library version in the console */
# endif
RxChannelPulse . attach ( RX_CHANNEL_PIN ) ;
ServoMotor [ NORMAL ] . attach ( SERVO1_PIN ) ; /* enumeration is used a index for the ServoMotor[] table */
ServoMotor [ INVERTED ] . attach ( SERVO2_PIN ) ; /* enumeration is used a index for the ServoMotor[]table */
pinMode ( LED_PIN , OUTPUT ) ;
}
void loop ( )
{
static uint16_t Width_us = NEUTRAL_US ; /* Static to keep the value at the next loop */
/* Receiver pulse acquisition and command of 2 servos, one in the direct direction, one in the inverted direction */
if ( RxChannelPulse . available ( ) )
{
AVERAGE ( Width_us , RxChannelPulse . width_us ( ) , AVERAGE_LEVEL ) ;
ServoMotor [ NORMAL ] . write_us ( Width_us ) ; /* Direct Signal */
ServoMotor [ INVERTED ] . write_us ( ( NEUTRAL_US * 2 ) - Width_us ) ; /* Inverted Signal */
SoftRcPulseOut : : refresh ( NOW ) ; /* NOW argument (=1) allows to synchronize outgoing pulses with incoming pulses */
RxPulseStartMs = millis ( ) ; /* Restart the Chrono for Pulse */
2015-01-14 18:08:45 -08:00
# if !defined(__AVR_ATtiny24__) && !defined(__AVR_ATtiny44__) && !defined(__AVR_ATtiny84__) && !defined(__AVR_ATtiny25__) && !defined(__AVR_ATtiny45__) && !defined(__AVR_ATtiny85__) && !defined(__AVR_ATtiny167__)
Serial . print ( " Pulse= " ) ; Serial . println ( Width_us ) ; /* For arduino UNO which has an hardware UART, display the library version in the console */
2014-12-19 08:45:50 -08:00
# endif
}
else
{
/* Check for pulse extinction */
if ( millis ( ) - RxPulseStartMs > = PULSE_MAX_PERIOD_MS )
{
/* Refresh the servos with the last known position in order to avoid "flabby" servos */
SoftRcPulseOut : : refresh ( NOW ) ; /* Immediate refresh of outgoing pulses */
RxPulseStartMs = millis ( ) ; /* Restart the Chrono for Pulse */
}
}
/* Blink LED Management */
if ( millis ( ) - LedStartMs > = LED_HALF_PERIOD_MS )
{
digitalWrite ( LED_PIN , LedState ) ;
LedState = ! LedState ; /* At the next loop, if the half period is elapsed, the LED state will be inverted */
LedStartMs = millis ( ) ; /* Restart the Chrono for the LED */
}
}