Add OLED library - update tiny wire libraries - add support for all PWM channels and PWM on pin 8

This commit is contained in:
Erik Tylek Kettenburg
2015-01-14 18:08:45 -08:00
parent fb93846380
commit 52f444d221
60 changed files with 3285 additions and 710 deletions

View File

@@ -17,7 +17,7 @@ This sequence uses:
IMPORTANT:
=========
For this sketch, which is using <DigiUSB> library:
1) Comment "#define RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT" in "arduino-1.xx\libraries\RcSeq.h".
1) Comment "#define RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT" AND #define RC_SEQ_CONTROL_SUPPORT in "arduino-1.xx\libraries\RcSeq.h".
This will disable the code to manage incoming RC pulses and save some flash memory.
RC_SEQ_WITH_SHORT_ACTION_SUPPORT and RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT shall be defined
2) Replace #define RING_BUFFER_SIZE 128 with #define RING_BUFFER_SIZE 32 in "arduino-1.xx\libraries\DigisparkUSB\DigiUSB.h".
@@ -38,17 +38,17 @@ static void ToggleLed(void); /* Declare Short Action: Toggle a LED */
#include <RcSeq.h>
#include <SoftRcPulseOut.h>
#define LED_PIN 1
#define LED_PIN 1
/*****************************************************************/
/* STEP #2: Enumeration of the servos used in the sequence */
/*****************************************************************/
enum {ROTATION_SERVO=0, UP_DOWN_SERVO , SERVO_NB};
enum {ROTATION_SERVO=0, UP_DOWN_SERVO, SERVO_NB};
/*****************************************************************/
/* STEP #3: Servos Digital Pins assignment */
/*****************************************************************/
#define UP_DOWN_SERVO_PIN 2
#define UP_DOWN_SERVO_PIN 2
/* /!\ Do not use Pin 3 (used by USB) /!\ */
/* /!\ Do not use Pin 4 (used by USB) /!\ */
#define ROTATION_SERVO_PIN 5
@@ -56,12 +56,12 @@ enum {ROTATION_SERVO=0, UP_DOWN_SERVO , SERVO_NB};
/**************************************************************************************/
/* STEP #4: Declaration of the angles of the servos for the different motions (in °) */
/**************************************************************************************/
#define UP_DOWN_ON_DECK_POS 120 /* Zodiac on the deck */
#define UP_DOWN_ON_AIR_POS 180 /* Zodiac in the air */
#define UP_DOWN_ON_SEA_POS 0 /* Zodiac at sea level */
#define UP_DOWN_ON_DECK_POS 120 /* Zodiac on the deck */
#define UP_DOWN_ON_AIR_POS 180 /* Zodiac in the air */
#define UP_DOWN_ON_SEA_POS 0 /* Zodiac at sea level */
#define ROTATION_ABOVE_DECK_POS 90 /* crane at deck side */
#define ROTATION_ABOVE_SEA_POS 0 /* crane at sea side */
#define ROTATION_ABOVE_DECK_POS 90 /* crane at deck side */
#define ROTATION_ABOVE_SEA_POS 0 /* crane at sea side */
/***************************************************************************************************************************************/
@@ -80,26 +80,26 @@ Order <--DECK_TO_AIR_DURATION_MS--> <--DECK_TO_SEA_ROTATION_DUR
/* STEP #6: With the help of the temporal diagram, declare start up time, the motion duration of servo and optional delay */
/**************************************************************************************************************************************************/
/* Tune below all the motion duration. Do not forget to add a trailer 'UL' for each value to force them in Unsigned Long type */
#define START_UP_DECK_TO_AIR_MS 0UL /* 0 for immediate start up, but you can put a delay here. Ex: 2000UL, will delay the startup of the whole sequence after 2 seconds */
#define DECK_TO_AIR_DURATION_MS 3000UL
#define START_UP_DECK_TO_AIR_MS 0UL /* 0 for immediate start up, but you can put a delay here. Ex: 2000UL, will delay the startup of the whole sequence after 2 seconds */
#define DECK_TO_AIR_DURATION_MS 3000UL
#define START_UP_DECK_TO_SEA_ROTATION_MS (START_UP_DECK_TO_AIR_MS + DECK_TO_AIR_DURATION_MS)
#define DECK_TO_SEA_ROTATION_DURATION_MS 3000UL
#define START_UP_DECK_TO_SEA_ROTATION_MS (START_UP_DECK_TO_AIR_MS + DECK_TO_AIR_DURATION_MS)
#define DECK_TO_SEA_ROTATION_DURATION_MS 3000UL
#define START_UP_AIR_TO_SEA_FALLING_MS (START_UP_DECK_TO_SEA_ROTATION_MS + DECK_TO_SEA_ROTATION_DURATION_MS)
#define AIR_TO_SEA_FALLING_DURATION_MS 9000UL
#define START_UP_AIR_TO_SEA_FALLING_MS (START_UP_DECK_TO_SEA_ROTATION_MS + DECK_TO_SEA_ROTATION_DURATION_MS)
#define AIR_TO_SEA_FALLING_DURATION_MS 9000UL
#define DELAY_BEFORE_RISING_UP_MS 6000UL
#define DELAY_BEFORE_RISING_UP_MS 6000UL
#define START_UP_SEA_TO_AIR_RISING_MS (START_UP_AIR_TO_SEA_FALLING_MS + AIR_TO_SEA_FALLING_DURATION_MS + DELAY_BEFORE_RISING_UP_MS)
#define SEA_TO_AIR_RISING_DURATION_MS 9000UL
#define START_UP_SEA_TO_AIR_RISING_MS (START_UP_AIR_TO_SEA_FALLING_MS + AIR_TO_SEA_FALLING_DURATION_MS + DELAY_BEFORE_RISING_UP_MS)
#define SEA_TO_AIR_RISING_DURATION_MS 9000UL
#define START_UP_SEA_TO_DECK_ROTATION_MS (START_UP_SEA_TO_AIR_RISING_MS + SEA_TO_AIR_RISING_DURATION_MS)
#define SEA_TO_DECK_ROTATION_DURATION_MS 3000UL
#define START_UP_SEA_TO_DECK_ROTATION_MS (START_UP_SEA_TO_AIR_RISING_MS + SEA_TO_AIR_RISING_DURATION_MS)
#define SEA_TO_DECK_ROTATION_DURATION_MS 3000UL
#define START_UP_AIR_TO_DECK_FALLING_MS (START_UP_SEA_TO_DECK_ROTATION_MS + SEA_TO_DECK_ROTATION_DURATION_MS)
#define AIR_TO_DECK_FALLING_DURATION_MS 3000UL
#define START_UP_AIR_TO_DECK_FALLING_MS (START_UP_SEA_TO_DECK_ROTATION_MS + SEA_TO_DECK_ROTATION_DURATION_MS)
#define AIR_TO_DECK_FALLING_DURATION_MS 3000UL
/********************************************************************************************************************/
/* STEP #7: Declare here the percentage of motion to be performed at half speed for servo start up and stop */
@@ -118,7 +118,7 @@ Order <--DECK_TO_AIR_DURATION_MS--> <--DECK_TO_SEA_ROTATION_DUR
/* - Percentage of motion performed at half speed for servo start and servo stop (Soft start and Soft stop) */
/* Note: START_STOP_PER_CENT not used (MOTION_WITHOUT_SOFT_START_AND_STOP() macro used) */
/************************************************************************************************************/
SequenceSt_t ZodiacSequence[] PROGMEM = {
const SequenceSt_t ZodiacSequence[] PROGMEM = {
SHORT_ACTION_TO_PERFORM(ToggleLed, START_UP_DECK_TO_AIR_MS) /* Switch ON the Led at the beginning of the sequence */
SHORT_ACTION_TO_PERFORM(ToggleLed, START_UP_AIR_TO_DECK_FALLING_MS+AIR_TO_DECK_FALLING_DURATION_MS) /* Switch OFF the Led at the beginning of the sequence: You are not obliged to put this line at the end of the table */
/* 1) The crane lifts the pneumatic Zodiac from the deck to the air and stops */
@@ -155,7 +155,7 @@ void setup()
/**************************************************************************************************************************/
/* STEP #11: declare the sequence command signal (0), the stick level (0), and the sequence to call */
/**************************************************************************************************************************/
RcSeq_DeclareCommandAndSequence(0, 0, RC_SEQUENCE(ZodiacSequence)); /* 0,0 since there's no RC command */
RcSeq_DeclareCommandAndSequence(0, 0, RC_SEQUENCE(ZodiacSequence)); /* 0, 0 since there's no RC command */
}
void loop()
@@ -172,12 +172,12 @@ char RxChar;
/****************************************************************************************************************/
if(DigiUSB.available())
{
RxChar=DigiUSB.read();
if(RxChar=='g') /* Go ! */
RxChar = DigiUSB.read();
if(RxChar == 'g') /* Go ! */
{
RcSeq_LaunchSequence(ZodiacSequence);
}
if(RxChar=='t') /* Toggle LED ! */
if(RxChar == 't') /* Toggle LED ! */
{
RcSeq_LaunchShortAction(ToggleLed); /* You can toggle LED during Servo Motion! */
}
@@ -187,7 +187,7 @@ char RxChar;
static void ToggleLed(void)
{
static boolean Status=LOW;
Status=!Status; /* Toggle Status */
static boolean Status = LOW;
Status = !Status; /* Toggle Status */
digitalWrite(LED_PIN, Status);
}
}

View File

@@ -81,11 +81,11 @@ enum {RC_CHANNEL, RC_CHANNEL_NB}; /* Here, as there is a single channel, we coul
/* Declaration of the custom keyboard": the pulse width of the push buttons do not need to be equidistant */
enum {PUSH_BUTTON1, PUSH_BUTTON2, PUSH_BUTTON3, PUSH_BUTTON4, PUSH_BUTTON5, PUSH_BUTTON_NBR};
#define TOLERANCE 40 /* Tolerance +/- (in microseconds): CAUTION, no overlap allowed between 2 adjacent active areas . active area width = 2 x TOLERANCE (us) */
KeyMap_t CustomKeyboard[] PROGMEM ={ {CENTER_VALUE_US(1100,TOLERANCE)}, /* PUSH_BUTTON1: +/-40 us */
{CENTER_VALUE_US(1300,TOLERANCE)}, /* PUSH_BUTTON2: +/-40 us */
{CENTER_VALUE_US(1500,TOLERANCE)}, /* PUSH_BUTTON3: +/-40 us */
{CENTER_VALUE_US(1700,TOLERANCE)}, /* PUSH_BUTTON4: +/-40 us */
{CENTER_VALUE_US(1900,TOLERANCE)}, /* PUSH_BUTTON5: +/-40 us */
const KeyMap_t CustomKeyboard[] PROGMEM ={ {CENTER_VALUE_US(1100,TOLERANCE)}, /* PUSH_BUTTON1: +/-40 us */
{CENTER_VALUE_US(1300,TOLERANCE)}, /* PUSH_BUTTON2: +/-40 us */
{CENTER_VALUE_US(1500,TOLERANCE)}, /* PUSH_BUTTON3: +/-40 us */
{CENTER_VALUE_US(1700,TOLERANCE)}, /* PUSH_BUTTON4: +/-40 us */
{CENTER_VALUE_US(1900,TOLERANCE)}, /* PUSH_BUTTON5: +/-40 us */
};
//==============================================================================================

View File

@@ -0,0 +1,307 @@
/*
This sketch illustrates 2 new features of the <RcSeq> library (since the V2.1 version):
1) the "control" capability: it's a function passed as argument to the RcSeq_DeclareCommandAndSequence() method.
It is used to check if a sequence can be launched or not, depending of specific condition
It is also used to inform the sequence is finished: this can be used to memorize in EEPROM the sequence id.
Like that, at the next start-up the position of the servos can be restored according to the last position of the sequence.
2) the "timeout" capability:
The RcSeq_Timeout() method can be used to check if the command signal remains constant (HIGH or LOW).
It's then possible to launch the sequence based on the static state of the command pin rather than a Rc Pulse width.
In practice, it's possible to use both manners to launch a sequence as done in the sketch below.
THE SKETCH:
==========
In this sketch, the first declared sequence opens the 2 doors with the help of 2 servos (1 per door).
The second declared sequence closes the 2 doors with the help of 2 servos (1 per door).
The 2 doors cannot open or close simultaneously with the same speed since there is a nosing secured to the right door.
This nosing forces to open and close the doors using sequences.
Opening <- -> Opening
. .
. .
. .
. .
. .
. .
. .
__ nosing -> .------. __
/ \----------------'---. '----------------/ \
\__/-------------------''-------------------\__/
Left door Right door
TOP VIEW
The opening sequence is like hereafter:
======================================
1) The servo assigned to the right door starts
2) Once rigth door slightly opened, the servo assigned to the left door starts, whilst the servo assigned to the right door resumes its travel
3) Once the 2 servos reached 90°, the 2 doors stop; the opening sequence is finished
The closing sequence is like hereafter:
======================================
1) The 2 servos assigned to the left and right doors start together but the left servo rotates more quickly than the right servo.
2) As a consequence, the left door is closed berfore the right door
3) Once the 2 servos reached 90°, the 2 doors stop; the closing sequence is finished
The sequences of this sketch can be launched either a RC channel either a regular ON/OFF switch:
===============================================================================================
A) Command from a RC channel:
------------------------- _______________
V _______________ | __ |
| __________ | ARDUINO: |________| / \ Left |
| | | | | | \__/ Servo |
| | RC |CH | UNO | |_______________|
'-+ Receiver |----| MEGA | _______________
| | | Digispark | | __ |
|__________| | Digispark pro |________| / \ Right |
|_______________| | \__/ Servo |
|_______________|
B) Command from a ON/OFF switch:
---------------------------- _______________
_______________ | __ |
| ARDUINO: |________| / \ Left |
| | | \__/ Servo |
| UNO | |_______________|
.----| MEGA | _______________
| | Digispark | | __ |
ON/OFF Switch \ | Digispark pro |________| / \ Right |
| |_______________| | \__/ Servo |
-+- |_______________|
GND
*/
/*************************************************/
/* STEP #1: Include the required libraries */
/*************************************************/
#include <RcSeq.h>
#include <TinyPinChange.h>
#include <SoftRcPulseIn.h>
#include <SoftRcPulseOut.h>
#include <EEPROM.h>
/*****************************************************************/
/* STEP #2: Enumeration of the RC Signals used in the sequence */
/*****************************************************************/
enum {RC_SIGNAL = 0, SIGNAL_NB}; /* Here, a single RC signal is used */
/******************************************************************/
/* STEP #3: Enumeration of the different position of the RC stick */
/******************************************************************/
enum {RC_PULSE_LEVEL_MINUS_1 = 0, RC_PULSE_LEVEL_PLUS_1, RC_PULSE_NB};
/*****************************************************************/
/* STEP #4: Enumeration of the servos used in the sequences */
/*****************************************************************/
enum {DOOR_SERVO_LEFT = 0, DOOR_SERVO_RIGHT, SERVO_NB}; /* In this sketch, 2 servos are declared */
/***************************************************/
/* STEP #5: Digital pin assignment for Command */
/***************************************************/
#define COMMAND_PIN 2 /* This pin can be connected to a channel of a RC Receiver or to a regular ON/OFF switch (switch wired between pin and Ground) */
/**************************************************/
/* STEP #6: Digital Pins assignment for Servos */
/**************************************************/
#define DOOR_SERVO_LEFT_PIN 3
#define DOOR_SERVO_RIGHT_PIN 4
/*************************************************************************************/
/* STEP #7: Declaration of the angle of the servos for the different motions (in °) */
/*************************************************************************************/
#define DOOR_SERVO_OPENED_LEFT_POS 135 /* position of the left Servo when left door is opened */
#define DOOR_SERVO_CLOSED_LEFT_POS 45 /* position of the left Servo when left door is closed */
#define DOOR_SERVO_OPENED_RIGHT_POS 45 /* position of the right Servo when right door is opened */
#define DOOR_SERVO_CLOSED_RIGHT_POS 135 /* position of the right Servo when right door is closed */
/***************************************************************************************************************************************/
/* STEP #8: Do a temporal diagram showing the start up and the duration of each motions of each servo */
/***************************************************************************************************************************************/
/*
1) OPENING MOTION OF THE DOORS
===========================
All the start up values (time stamp) have as reference the moment of the sequence startup order (t=0).
1.1 MOTION OF THE LEFT DOOR SERVO FOR OPENING
=========================================
Order <---OPENING_DURATION_LEFT_MS--->
|-----------------------------|--------------------------------|-->Time Axis
0 OPENING_START_LEFT_MS
1.2 MOTION OF THE RIGHT DOOR SERVO FOR OPENING
==========================================
Order <--------OPENING_DURATION_RIGHT_MS------->
|-------------------|------------------------------------------|-->Time Axis
0 OPENING_START_RIGHT_MS
2) CLOSING MOTION OF THE DOORS
===========================
All the start up values (time stamp) have as reference the moment of the sequence startup order (t=0).
2.1 MOTION OF THE LEFT DOOR SERVO FOR CLOSING
=========================================
Order <---CLOSING_DURATION_LEFT_MS--->
|-------------------|--------------------------------|------------>Time Axis
0 CLOSING_START_LEFT_MS
2.2 MOTION OF THE RIGTH DOOR SERVO FOR CLOSING
==========================================
Order <--------CLOSING_DURATION_RIGHT_MS------->
|-------------------|------------------------------------------|-->Time Axis
0 CLOSING_START_RIGHT_MS
*/
/**************************************************************************************************************************************************/
/* STEP #9: With the help of the temporal diagram, declare start up time, the motion duration of servo and optional delay */
/**************************************************************************************************************************************************/
/* Tune below all the motion duration. Do not forget to add a trailer 'UL' for each value to force them in Unsigned Long type */
#define OPENING_START_LEFT_MS 500UL //This means the left servo motion will be delayed of 500ms AFTER the order
#define OPENING_DURATION_LEFT_MS 2500UL //The left door motion ends after 500+2500=3s, as the right door
#define OPENING_START_RIGHT_MS 0UL //Immediate start
#define OPENING_DURATION_RIGHT_MS 3000UL //The right door motion ends after 3s
#define CLOSING_START_LEFT_MS 0UL //Immediate start
#define CLOSING_DURATION_LEFT_MS 3000UL //The left door will be closed BEFORE the right door
#define CLOSING_START_RIGHT_MS 0UL //Immediate start
#define CLOSING_DURATION_RIGHT_MS 4000UL //The right door will be closed AFTER the left door
/********************************************************************************************************************/
/* STEP #10: Declare here the percentage of motion to be performed at half speed for servo start up and stop */
/********************************************************************************************************************/
#define START_STOP_PER_CENT 5 /* Percentage of motion performed at half-speed for starting and stopping the servos (Soft start et Soft stop) */
/************************************************************************************************************/
/* STEP #11: Use a "const SequenceSt_t" structure table to declare the servo sequence */
/* For each table entry, arguments are: */
/* - Servo Index */
/* - Initial Servo Position in ° */
/* - Final Servo Position in ° */
/* - Motion Start Time Stamp in ms */
/* - Motion duration in ms between initial and final position */
/* - Percentage of motion performed at half speed for servo start and servo stop (Soft start and Soft stop) */
/************************************************************************************************************/
/* Table describing the motions of the 2 servos for opening the 2 doors */
const SequenceSt_t OpeningSequence[] PROGMEM = {/* Servo Id , Initial Angle , Final Angle , Delay after order , Motion Duration , Percentage at half speed */
/* 1st Servo */ MOTION_WITH_SOFT_START_AND_STOP(DOOR_SERVO_LEFT, DOOR_SERVO_CLOSED_LEFT_POS, DOOR_SERVO_OPENED_LEFT_POS, OPENING_START_LEFT_MS, OPENING_DURATION_LEFT_MS, START_STOP_PER_CENT)
/* 2nd Servo */ MOTION_WITH_SOFT_START_AND_STOP(DOOR_SERVO_RIGHT, DOOR_SERVO_CLOSED_RIGHT_POS, DOOR_SERVO_OPENED_RIGHT_POS, OPENING_START_RIGHT_MS, OPENING_DURATION_RIGHT_MS, START_STOP_PER_CENT)
};
/* Table describing the motions of the 2 servos for closing the 2 doors */
const SequenceSt_t ClosingSequence[] PROGMEM = {/* Servo Id , Initial Angle , Final Angle , Delai after order , Motion Duration , Percentage at half speed */
/* 1st Servo */ MOTION_WITH_SOFT_START_AND_STOP(DOOR_SERVO_LEFT, DOOR_SERVO_OPENED_LEFT_POS, DOOR_SERVO_CLOSED_LEFT_POS, CLOSING_START_LEFT_MS, CLOSING_DURATION_LEFT_MS, START_STOP_PER_CENT)
/* 2nd Servo */ MOTION_WITH_SOFT_START_AND_STOP(DOOR_SERVO_RIGHT, DOOR_SERVO_OPENED_RIGHT_POS, DOOR_SERVO_CLOSED_RIGHT_POS, CLOSING_START_RIGHT_MS, CLOSING_DURATION_RIGHT_MS, START_STOP_PER_CENT)
};
enum {COMMAND_OPEN = 0, COMMAND_CLOSE};
/* GLOBAL VARIABLES */
uint8_t LastExecutedSeqIdx;
void setup()
{
#if !defined(__AVR_ATtiny24__) && !defined(__AVR_ATtiny44__) && !defined(__AVR_ATtiny84__) && !defined(__AVR_ATtiny25__) && !defined(__AVR_ATtiny45__) && !defined(__AVR_ATtiny85__) && !defined(__AVR_ATtiny167__)
Serial.begin(9600);
Serial.print(F("RcSeq library V"));Serial.print(RcSeq_LibTextVersionRevision());Serial.println(F(" demo: advanced doors sequences"));
#endif
/***************************************************************************/
/* STEP #12: Init <RcSeq> library */
/***************************************************************************/
RcSeq_Init();
/****************************************************************************************/
/* STEP #13: declare the servo command signals with their digital pin number */
/****************************************************************************************/
RcSeq_DeclareSignal(RC_SIGNAL, COMMAND_PIN);
/******************************************************************************************/
/* STEP #14: declare a stick assigned to the RC signal having RC_PULSE_NB positions */
/******************************************************************************************/
RcSeq_DeclareStick(RC_SIGNAL, 1000, 2000, RC_PULSE_NB);
/****************************************************************************************/
/* STEP #15: declare the servo command signals with their digital pin number */
/****************************************************************************************/
RcSeq_DeclareServo(DOOR_SERVO_LEFT, DOOR_SERVO_LEFT_PIN);
RcSeq_DeclareServo(DOOR_SERVO_RIGHT, DOOR_SERVO_RIGHT_PIN);
/*******************************************************************************************************/
/* STEP #16: declare the sequence assigned to specific position of the stick assigned to the RC signal */
/*******************************************************************************************************/
RcSeq_DeclareCommandAndSequence(RC_SIGNAL, RC_PULSE_LEVEL_MINUS_1, RC_SEQUENCE(OpeningSequence), Control); // Declare a sequence triggered by a RC pulse Level Minus 1 (stick at extreme position during at least 250 ms)
RcSeq_DeclareCommandAndSequence(RC_SIGNAL, RC_PULSE_LEVEL_PLUS_1, RC_SEQUENCE(ClosingSequence), Control); // Declare a sequence triggered by a RC pulse Level Plus 1 (stick at extreme position during at least 250 ms)
/*******************************************************************************************/
/* STEP #17: Initialize the position of the servos according to the last finished sequence */
/*******************************************************************************************/
LastExecutedSeqIdx = EEPROM.read(0);
if (LastExecutedSeqIdx == COMMAND_OPEN)
{
RcSeq_ServoWrite(DOOR_SERVO_LEFT, DOOR_SERVO_OPENED_LEFT_POS);
RcSeq_ServoWrite(DOOR_SERVO_RIGHT, DOOR_SERVO_OPENED_RIGHT_POS);
}
else
{
RcSeq_ServoWrite(DOOR_SERVO_LEFT, DOOR_SERVO_CLOSED_LEFT_POS);
RcSeq_ServoWrite(DOOR_SERVO_RIGHT, DOOR_SERVO_CLOSED_RIGHT_POS);
}
}
void loop()
{
uint8_t RcSignalPinState;
/****************************************************************************************************************/
/* STEP #18: call the refresh function inside the loop() to catch RC commands and to manage the servo positions */
/****************************************************************************************************************/
RcSeq_Refresh();
/*********************************************************************************************************/
/* STEP #19: optionally, allow launching the Sequences ou Actions on Timeout (cmd with a regular switch) */
/*********************************************************************************************************/
if (RcSeq_SignalTimeout(RC_SIGNAL, 250, &RcSignalPinState))
{
/* Launch the"OpeningSequence" sequence if a LOW level is present during at least 250ms: this allows testing the sequence of servo without using a RC set, just using a regular switch */
if((LastExecutedSeqIdx == COMMAND_CLOSE) && (RcSignalPinState == LOW))
{
RcSeq_LaunchSequence(OpeningSequence);
}
/* Launch the"ClosingSequence" sequence if a HIGH level is present during at least 250ms: this allows testing the sequence of servo without using a RC set, just using a regular switch */
if((LastExecutedSeqIdx == COMMAND_OPEN) && (RcSignalPinState == HIGH))
{
RcSeq_LaunchSequence(ClosingSequence);
}
}
}
/* The Control() fonction is automatically called by the RcSeq library */
uint8_t Control(uint8_t Action, uint8_t SeqIdx)
{
uint8_t Ret = 0;
#if !defined(__AVR_ATtiny24__) && !defined(__AVR_ATtiny44__) && !defined(__AVR_ATtiny84__) && !defined(__AVR_ATtiny25__) && !defined(__AVR_ATtiny45__) && !defined(__AVR_ATtiny85__) && !defined(__AVR_ATtiny167__)
Serial.print("Action=");Serial.print(Action);Serial.print(" SeqIdx=");Serial.println(SeqIdx);
#endif
switch(Action)
{
case RC_SEQ_START_CONDITION: /* RcSeq asks if the conditions are met to launch the sequence SeqIdx */
/* Put here a condition to allow RcSeq launching the sequence SeqIdx (Put Ret=1 if no specific condition) */
Ret = (SeqIdx != LastExecutedSeqIdx); /* Allows RcSeq launching the sequence if the sequence to launch is different from the last one */
break;
case RC_SEQ_END_OF_SEQ: /* RcSeq informs the sequence SeqIdx is finished */
/* We memorize the last finished sequence id in EEPROM memory. Like that, at next power-up, we will know how to position the servos ( done in the Setup() ) */
EEPROM.write(0, SeqIdx);
LastExecutedSeqIdx = SeqIdx;
break;
}
return(Ret);
}

View File

@@ -1,7 +1,7 @@
#include <RcSeq.h>
#include <TinyPinChange.h> /* Ne pas oublier d'inclure la librairie <TinyPinChange> qui est utilisee par la librairie <RcSeq> */
#include <SoftRcPulseIn.h> /* Ne pas oublier d'inclure la librairie <SoftRcPulseIn> qui est utilisee par la librairie <RcSeq> */
#include <SoftRcPulseOut.h> /* Ne pas oublier d'inclure la librairie <SoftRcPulseOut> qui est utilisee par la librairie <RcSeq> */
#include <TinyPinChange.h>
#include <SoftRcPulseIn.h>
#include <SoftRcPulseOut.h>
/*
IMPORTANT:
@@ -25,16 +25,16 @@ enum {RC_VOIE1, RC_VOIE2, RC_VOIE3, NBR_VOIES_RC}; /* Declaration des voies */
enum {BP1, BP2, NBR_BP}; /* Declaration des Boutons-Poussoirs (On peut aller jusqu'à BP8) */
enum {POS_MINUS1, POS_PLUS1,NBR_POS}; /* Declaration des positions du Manche on peut aller de POS_MOINS2 à POS_PLUS2 (4 Positions actives Max)*/
enum {POS_MINUS1, POS_PLUS1, NBR_POS}; /* Declaration des positions du Manche on peut aller de POS_MOINS2 à POS_PLUS2 (4 Positions actives Max)*/
/* Declaration d'un clavier "Maison": les impulsions des Boutons-Poussoirs n'ont pas besoin d'etre equidistantes */
enum {BP_MAISON1, BP_MAISON2, BP_MAISON3, NBR_BP_MAISON};
#define TOLERANCE 40 /* Tolerance en + ou en - (en micro-seconde) */
KeyMap_t ClavierMaison[] PROGMEM ={ {VALEUR_CENTRALE_US(1100,TOLERANCE)}, /* BP_MAISON1: 1100 +/-40 us */
{VALEUR_CENTRALE_US(1300,TOLERANCE)}, /* BP_MAISON2: 1300 +/-40 us */
{VALEUR_CENTRALE_US(1700,TOLERANCE)}, /* BP_MAISON3: 1700 +/-40 us */
};
const KeyMap_t ClavierMaison[] PROGMEM ={ {VALEUR_CENTRALE_US(1100, TOLERANCE)}, /* BP_MAISON1: 1100 +/-40 us */
{VALEUR_CENTRALE_US(1300, TOLERANCE)}, /* BP_MAISON2: 1300 +/-40 us */
{VALEUR_CENTRALE_US(1700, TOLERANCE)}, /* BP_MAISON3: 1700 +/-40 us */
};
enum {AZIMUT=0, ELEVATION , NBR_SERVO}; /* Delaration de tous les servos, 2 dans cet exemple (On peut déclaer jusqu'à 8 servos) */
@@ -80,23 +80,23 @@ enum {AZIMUT=0, ELEVATION , NBR_SERVO}; /* Delaration de tous les servos, 2 dans
#define DEM_ARRET_POUR_CENT 5 /* Pourcentage du mouvement devant etre effectue a mi-vitesse pour demarrage servo et arret servo (Soft start et Soft stop) */
/* Declaration de la table de sequence des mouvements des servo et des actions courtes */
SequenceSt_t SequenceServoEtActionCourte[] PROGMEM = {
ACTION_COURTE_A_EFFECTUER(InverseLed,DEMARRAGE_MONTEE_PONT_HAUT_MS)
const SequenceSt_t SequenceServoEtActionCourte[] PROGMEM = {
ACTION_COURTE_A_EFFECTUER(InverseLed, DEMARRAGE_MONTEE_PONT_HAUT_MS)
/* Montee du Zodiac du pont vers la position haute */
MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS(ELEVATION,ELEVATION_POS_PONT,ELEVATION_POS_HAUT,DEMARRAGE_MONTEE_PONT_HAUT_MS,DUREE_MONTEE_PONT_HAUT_MS,DEM_ARRET_POUR_CENT)
MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS(ELEVATION, ELEVATION_POS_PONT, ELEVATION_POS_HAUT, DEMARRAGE_MONTEE_PONT_HAUT_MS, DUREE_MONTEE_PONT_HAUT_MS, DEM_ARRET_POUR_CENT)
/* Rotation Grue du pont vers la mer */
MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS(AZIMUT,AZIMUT_POS_PONT,AZIMUT_POS_MER,DEMARRAGE_ROTATION_PONT_MER_MS,DUREE_ROTATION_PONT_MER_MS,DEM_ARRET_POUR_CENT)
MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS(AZIMUT, AZIMUT_POS_PONT, AZIMUT_POS_MER, DEMARRAGE_ROTATION_PONT_MER_MS, DUREE_ROTATION_PONT_MER_MS, DEM_ARRET_POUR_CENT)
/* Descente du Zodiac depuis la position haute vers la la mer */
MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS(ELEVATION,ELEVATION_POS_HAUT,ELEVATION_POS_MER,DEMARRAGE_DESCENTE_HAUT_MER_MS,DUREE_DESCENTE_HAUT_MER_MS,DEM_ARRET_POUR_CENT)
ACTION_COURTE_A_EFFECTUER(InverseLed,DEMARRAGE_DESCENTE_HAUT_MER_MS+DUREE_DESCENTE_HAUT_MER_MS)
ACTION_COURTE_A_EFFECTUER(InverseLed,DEMARRAGE_MONTEE_MER_HAUT_MS)
MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS(ELEVATION, ELEVATION_POS_HAUT, ELEVATION_POS_MER, DEMARRAGE_DESCENTE_HAUT_MER_MS, DUREE_DESCENTE_HAUT_MER_MS, DEM_ARRET_POUR_CENT)
ACTION_COURTE_A_EFFECTUER(InverseLed, DEMARRAGE_DESCENTE_HAUT_MER_MS + DUREE_DESCENTE_HAUT_MER_MS)
ACTION_COURTE_A_EFFECTUER(InverseLed, DEMARRAGE_MONTEE_MER_HAUT_MS)
/* Montee du Zodiac de la mer vers la position haute */
MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS(ELEVATION,ELEVATION_POS_MER,ELEVATION_POS_HAUT,DEMARRAGE_MONTEE_MER_HAUT_MS,DUREE_MONTEE_MER_HAUT_MS,DEM_ARRET_POUR_CENT)
MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS(ELEVATION, ELEVATION_POS_MER, ELEVATION_POS_HAUT, DEMARRAGE_MONTEE_MER_HAUT_MS, DUREE_MONTEE_MER_HAUT_MS, DEM_ARRET_POUR_CENT)
/* Rotation Grue de la mer vers le pont */
MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS(AZIMUT,AZIMUT_POS_MER,AZIMUT_POS_PONT,DEMARRAGE_ROTATION_MER_PONT_MS,DUREE_ROTATION_MER_PONT_MS,DEM_ARRET_POUR_CENT)
MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS(AZIMUT, AZIMUT_POS_MER, AZIMUT_POS_PONT, DEMARRAGE_ROTATION_MER_PONT_MS, DUREE_ROTATION_MER_PONT_MS, DEM_ARRET_POUR_CENT)
/* Descente du Zodiac de la position haute vers le pont */
MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS(ELEVATION,ELEVATION_POS_HAUT,ELEVATION_POS_PONT,DEMARRAGE_DESCENTE_HAUT_PONT_MS,DUREE_DESCENTE_HAUT_PONT_MS,DEM_ARRET_POUR_CENT)
ACTION_COURTE_A_EFFECTUER(InverseLed,DEMARRAGE_DESCENTE_HAUT_PONT_MS+DUREE_DESCENTE_HAUT_PONT_MS)
MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS(ELEVATION, ELEVATION_POS_HAUT, ELEVATION_POS_PONT, DEMARRAGE_DESCENTE_HAUT_PONT_MS, DUREE_DESCENTE_HAUT_PONT_MS, DEM_ARRET_POUR_CENT)
ACTION_COURTE_A_EFFECTUER(InverseLed, DEMARRAGE_DESCENTE_HAUT_PONT_MS + DUREE_DESCENTE_HAUT_PONT_MS)
};
#define LED 13
@@ -114,22 +114,22 @@ void setup()
RcSeq_DeclareServo(AZIMUT, BROCHE_SIGNAL_SERVO_AZ);
/* Commande d'une action courte et d'une sequence de servos avec 2 BP du clavier de la VOIE1 */
RcSeq_DeclareSignal(RC_VOIE1,BROCHE_SIGNAL_RECEPTEUR_VOIE1);
RcSeq_DeclareSignal(RC_VOIE1, BROCHE_SIGNAL_RECEPTEUR_VOIE1);
RcSeq_DeclareClavier(RC_VOIE1, 1000, 2000, NBR_BP);
RcSeq_DeclareCommandeEtActionCourte(RC_VOIE1, BP1, InverseLed);
RcSeq_DeclareCommandeEtSequence(RC_VOIE1, BP2, RC_SEQUENCE(SequenceServoEtActionCourte));
RcSeq_DeclareCommandeEtSequence(RC_VOIE1, BP2, RC_SEQUENCE(SequenceServoEtActionCourte), NULL);
/* Commande d'une action courte et d'une sequence de servos avec le manche de la VOIE2 */
RcSeq_DeclareSignal(RC_VOIE2,BROCHE_SIGNAL_RECEPTEUR_VOIE2);
RcSeq_DeclareSignal(RC_VOIE2, BROCHE_SIGNAL_RECEPTEUR_VOIE2);
RcSeq_DeclareManche(RC_VOIE2, 1000, 2000, NBR_POS);
RcSeq_DeclareCommandeEtActionCourte(RC_VOIE2, POS_MINUS1, InverseLed);
RcSeq_DeclareCommandeEtSequence(RC_VOIE2, POS_PLUS1, RC_SEQUENCE(SequenceServoEtActionCourte));
RcSeq_DeclareCommandeEtSequence(RC_VOIE2, POS_PLUS1, RC_SEQUENCE(SequenceServoEtActionCourte), NULL);
/* Commande d'une action courte et d'une sequence de servos avec le clavier "maison" de la VOIE3 */
RcSeq_DeclareSignal(RC_VOIE3,BROCHE_SIGNAL_RECEPTEUR_VOIE3);
RcSeq_DeclareSignal(RC_VOIE3, BROCHE_SIGNAL_RECEPTEUR_VOIE3);
RcSeq_DeclareClavierMaison(RC_VOIE3, RC_CLAVIER_MAISON(ClavierMaison));
RcSeq_DeclareCommandeEtActionCourte(RC_VOIE3, BP_MAISON1, InverseLed);
RcSeq_DeclareCommandeEtSequence(RC_VOIE3, BP_MAISON3, RC_SEQUENCE(SequenceServoEtActionCourte));
RcSeq_DeclareCommandeEtSequence(RC_VOIE3, BP_MAISON3, RC_SEQUENCE(SequenceServoEtActionCourte), NULL);
pinMode(LED, OUTPUT);
}
@@ -142,13 +142,13 @@ void loop()
/* Action associee au BP1 de la VOIE1 ou au manche position basse de la VOIE2 ou au BP_MAISON1 de la VOIE3 */
void InverseLed(void)
{
static uint32_t DebutMs=millis(); /* static, pour conserver l'etat entre 2 appels de la fonction */
static boolean Etat=HIGH; /* static, pour conserver l'etat entre 2 appels de la fonction */
static uint32_t DebutMs = millis(); /* static, pour conserver l'etat entre 2 appels de la fonction */
static boolean Etat = HIGH; /* static, pour conserver l'etat entre 2 appels de la fonction */
if(millis() - DebutMs >= 500UL) /* Depuis RcSeq V2.0, la tempo inter-commande doit etre geree dans le sketch utilisateur */
{
DebutMs=millis();
DebutMs = millis();
digitalWrite(LED, Etat);
Etat=!Etat; /* Au prochain appel de InverseLed(), l'etat de la LED sera inverse */
Etat = !Etat; /* Au prochain appel de InverseLed(), l'etat de la LED sera inverse */
}
}

View File

@@ -32,9 +32,9 @@ Cette sequence utilise:
/* ETAPE N°1: Inclure les 4 librairies necessaires */
/***************************************************/
#include <RcSeq.h>
#include <TinyPinChange.h> /* Ne pas oublier d'inclure la librairie <TinyPinChange> qui est utilisee par la librairie <RcSeq> */
#include <SoftRcPulseIn.h> /* Ne pas oublier d'inclure la librairie <SoftRcPulseIn> qui est utilisee par la librairie <RcSeq> */
#include <SoftRcPulseOut.h> /* Ne pas oublier d'inclure la librairie <SoftRcPulseOut> qui est utilisee par la librairie <RcSeq> */
#include <TinyPinChange.h>
#include <SoftRcPulseIn.h>
#include <SoftRcPulseOut.h>
/*****************************************************/
/* ETAPE N°2: Enumeration des signaux de commande RC */
@@ -121,23 +121,23 @@ Ordre <---DUREE_MONTEE_PONT_HAUT_MS--> <--DUREE_ROTATION_PONT_M
/* Il est possible d'inclure des actions courtes. Il suffit d'utiliser la macro ACTION_COURTE_A_EFFECTUER() en donnant le nom de la fonction a appeler et le */
/* moment ou l'action doit avoir lieu. Dans cet exemple, la LED s'allume pendant que les servos tournent et s'eteint pendant la pause de 6 secondes. */
/***************************************************************************************************************************************************************/
SequenceSt_t SequencePlus2[] PROGMEM = {
ACTION_COURTE_A_EFFECTUER(InverseLed,DEMARRAGE_MONTEE_PONT_HAUT_MS)
const SequenceSt_t SequencePlus2[] PROGMEM = {
ACTION_COURTE_A_EFFECTUER(InverseLed, DEMARRAGE_MONTEE_PONT_HAUT_MS)
/* Montee du Zodiac du pont vers la position haute */
MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS(ELEVATION,ELEVATION_POS_PONT,ELEVATION_POS_HAUT,DEMARRAGE_MONTEE_PONT_HAUT_MS,DUREE_MONTEE_PONT_HAUT_MS,DEM_ARRET_POUR_CENT)
MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS(ELEVATION, ELEVATION_POS_PONT, ELEVATION_POS_HAUT, DEMARRAGE_MONTEE_PONT_HAUT_MS, DUREE_MONTEE_PONT_HAUT_MS, DEM_ARRET_POUR_CENT)
/* Rotation Grue du pont vers la mer */
MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS(AZIMUT,AZIMUT_POS_PONT,AZIMUT_POS_MER,DEMARRAGE_ROTATION_PONT_MER_MS,DUREE_ROTATION_PONT_MER_MS,DEM_ARRET_POUR_CENT)
MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS(AZIMUT, AZIMUT_POS_PONT, AZIMUT_POS_MER, DEMARRAGE_ROTATION_PONT_MER_MS, DUREE_ROTATION_PONT_MER_MS, DEM_ARRET_POUR_CENT)
/* Descente du Zodiac depuis la position haute vers la la mer */
MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS(ELEVATION,ELEVATION_POS_HAUT,ELEVATION_POS_MER,DEMARRAGE_DESCENTE_HAUT_MER_MS,DUREE_DESCENTE_HAUT_MER_MS,DEM_ARRET_POUR_CENT)
ACTION_COURTE_A_EFFECTUER(InverseLed,DEMARRAGE_DESCENTE_HAUT_MER_MS+DUREE_DESCENTE_HAUT_MER_MS)
ACTION_COURTE_A_EFFECTUER(InverseLed,DEMARRAGE_MONTEE_MER_HAUT_MS)
MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS(ELEVATION, ELEVATION_POS_HAUT, ELEVATION_POS_MER, DEMARRAGE_DESCENTE_HAUT_MER_MS, DUREE_DESCENTE_HAUT_MER_MS, DEM_ARRET_POUR_CENT)
ACTION_COURTE_A_EFFECTUER(InverseLed, DEMARRAGE_DESCENTE_HAUT_MER_MS + DUREE_DESCENTE_HAUT_MER_MS)
ACTION_COURTE_A_EFFECTUER(InverseLed, DEMARRAGE_MONTEE_MER_HAUT_MS)
/* Montee du Zodiac de la mer vers la position haute */
MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS(ELEVATION,ELEVATION_POS_MER,ELEVATION_POS_HAUT,DEMARRAGE_MONTEE_MER_HAUT_MS,DUREE_MONTEE_MER_HAUT_MS,DEM_ARRET_POUR_CENT)
MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS(ELEVATION, ELEVATION_POS_MER, ELEVATION_POS_HAUT, DEMARRAGE_MONTEE_MER_HAUT_MS, DUREE_MONTEE_MER_HAUT_MS, DEM_ARRET_POUR_CENT)
/* Rotation Grue de la mer vers le pont */
MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS(AZIMUT,AZIMUT_POS_MER,AZIMUT_POS_PONT,DEMARRAGE_ROTATION_MER_PONT_MS,DUREE_ROTATION_MER_PONT_MS,DEM_ARRET_POUR_CENT)
MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS(AZIMUT, AZIMUT_POS_MER, AZIMUT_POS_PONT, DEMARRAGE_ROTATION_MER_PONT_MS, DUREE_ROTATION_MER_PONT_MS, DEM_ARRET_POUR_CENT)
/* Descente du Zodiac de la position haute vers le pont */
MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS(ELEVATION,ELEVATION_POS_HAUT,ELEVATION_POS_PONT,DEMARRAGE_DESCENTE_HAUT_PONT_MS,DUREE_DESCENTE_HAUT_PONT_MS,DEM_ARRET_POUR_CENT)
ACTION_COURTE_A_EFFECTUER(InverseLed,DEMARRAGE_DESCENTE_HAUT_PONT_MS+DUREE_DESCENTE_HAUT_PONT_MS)
MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS(ELEVATION, ELEVATION_POS_HAUT, ELEVATION_POS_PONT, DEMARRAGE_DESCENTE_HAUT_PONT_MS, DUREE_DESCENTE_HAUT_PONT_MS, DEM_ARRET_POUR_CENT)
ACTION_COURTE_A_EFFECTUER(InverseLed, DEMARRAGE_DESCENTE_HAUT_PONT_MS + DUREE_DESCENTE_HAUT_PONT_MS)
};
#define LED 13
@@ -158,7 +158,7 @@ void setup()
/**************************************************************************************/
/* ETAPE N°13: declarer le(s) signal(aux) de commande RC avec leur N° de pin digitale */
/**************************************************************************************/
RcSeq_DeclareSignal(SIGNAL_RC,BROCHE_SIGNAL_RECEPTEUR);
RcSeq_DeclareSignal(SIGNAL_RC, BROCHE_SIGNAL_RECEPTEUR);
/******************************************************************************************/
/* ETAPE N°14: que le signal RC est associe a un manche qui a NBR_RC_IMPULSIONS positions */
@@ -174,7 +174,7 @@ void setup()
/**************************************************************************************************************************/
/* ETAPE N°16: declarer le signal de commande de sequence, le niveau du manche, et la sequence ou action courte a appeler */
/**************************************************************************************************************************/
RcSeq_DeclareCommandeEtSequence(SIGNAL_RC, RC_IMPULSION_NIVEAU_PLUS_2, RC_SEQUENCE(SequencePlus2)); // Voici comment declarer une sequence actionnee par une impulsion Niveau Plus 2 (manche en position extreme pendant au moins 250 ms)
RcSeq_DeclareCommandeEtSequence(SIGNAL_RC, RC_IMPULSION_NIVEAU_PLUS_2, RC_SEQUENCE(SequencePlus2), NULL); // Voici comment declarer une sequence actionnee par une impulsion Niveau Plus 2 (manche en position extreme pendant au moins 250 ms)
pinMode(LED, OUTPUT);
RcSeq_DeclareCommandeEtActionCourte(SIGNAL_RC, RC_IMPULSION_NIVEAU_MOINS_1, InverseLed); // Voici comment declarer une action actionnee par une impulsion Niveau Moins 1 (manche en position mi-course pendant au moins 250 ms)

View File

@@ -30,31 +30,31 @@ enum {RC_VOIE, NBR_VOIES_RC}; /* Ici, comme il n'y a qu'une voie, on aurait pu f
/* Declaration d'un clavier "Maison": les impulsions des Boutons-Poussoirs n'ont pas besoin d'etre equidistantes */
enum {BP1, BP2, BP3, BP4, BP5, BP6, BP7, BP8, NBR_BP};
#define TOLERANCE 40 /* Tolerance en + ou en - (en micro-seconde): ATTENTION, il ne doit pas y avoir recouvrement entre 2 zones actives adjascentes. Zone active = 2 x TOLERANCE (us) */
KeyMap_t ClavierMaison[] PROGMEM ={ {VALEUR_CENTRALE_US(1100,TOLERANCE)}, /* BP1: +/-40 us */
{VALEUR_CENTRALE_US(1200,TOLERANCE)}, /* BP2: +/-40 us */
{VALEUR_CENTRALE_US(1300,TOLERANCE)}, /* BP3: +/-40 us */
{VALEUR_CENTRALE_US(1400,TOLERANCE)}, /* BP4: +/-40 us */
{VALEUR_CENTRALE_US(1600,TOLERANCE)}, /* BP5: +/-40 us */
{VALEUR_CENTRALE_US(1700,TOLERANCE)}, /* BP6: +/-40 us */
{VALEUR_CENTRALE_US(1800,TOLERANCE)}, /* BP7: +/-40 us */
{VALEUR_CENTRALE_US(1900,TOLERANCE)}, /* BP8: +/-40 us */
};
const KeyMap_t ClavierMaison[] PROGMEM ={ {VALEUR_CENTRALE_US(1100,TOLERANCE)}, /* BP1: +/-40 us */
{VALEUR_CENTRALE_US(1200,TOLERANCE)}, /* BP2: +/-40 us */
{VALEUR_CENTRALE_US(1300,TOLERANCE)}, /* BP3: +/-40 us */
{VALEUR_CENTRALE_US(1400,TOLERANCE)}, /* BP4: +/-40 us */
{VALEUR_CENTRALE_US(1600,TOLERANCE)}, /* BP5: +/-40 us */
{VALEUR_CENTRALE_US(1700,TOLERANCE)}, /* BP6: +/-40 us */
{VALEUR_CENTRALE_US(1800,TOLERANCE)}, /* BP7: +/-40 us */
{VALEUR_CENTRALE_US(1900,TOLERANCE)}, /* BP8: +/-40 us */
};
//==============================================================================================
/* Astuce: une macro pour n'ecrire qu'une seule fois la fonction ActionX() */
#define DECLARE_ACTION(Idx) \
void Action##Idx(void) \
{ \
static uint32_t DebutMs=millis(); \
static boolean Etat=HIGH; \
static uint32_t DebutMs = millis(); \
static boolean Etat = HIGH; \
/* Depuis la version 2.0 de la lib <RcSeq>, pour */ \
/* des raisons de reactivite, la tempo inter-commande */ \
/* doit etre geree dans le sketch utilisateur. */ \
if(millis() - DebutMs >= 500UL) \
{ \
DebutMs=millis(); \
DebutMs = millis(); \
digitalWrite(Idx, Etat); \
Etat=!Etat; \
Etat = !Etat; \
} \
}

View File

@@ -1,6 +1,6 @@
#include "RcSeq.h"
/*
English: by RC Navy (2012/2013)
English: by RC Navy (2012-2015)
=======
<RcSeq> is an asynchronous library for ATmega328P (UNO), ATtiny84 and ATtiny85 to easily create servo's sequences and/or to execute short actions from RC commands.
It can also be used to trig some short "actions" (the duration must be less than 20ms to not disturb the servo commands)
@@ -21,7 +21,7 @@
CAUTION: the end user shall also use asynchronous programmation method in the loop() function (no blocking functions such as delay() or pulseIn()).
http://p.loussouarn.free.fr
Francais: par RC Navy (2012/2013)
Francais: par RC Navy (2012-2015)
========
<RcSeq> est une librairie asynchrone pour ATmega328P (UNO), ATtiny84 et ATtiny85 pour creer facilement des sequences de servos et/ou executer des actions depuis des commandes RC.
Elle peut egalement etre utilisee pour lancer des "actions courtes" (la duree doit etre inferieure a 20ms pour ne pas perturber la commande des servos)
@@ -58,7 +58,7 @@
| | | \
| X O X | --> RC_IMPULSION_NIVEAU_MOINS_1 |
| | | |
| X O X | --> RC_IMPULSION_NIVEAU_MOINS_2 |
| X O X | --> RC_IMPULSION_NIVEAU_MOINS_2 |
'---------------------' /
| | | | |
| | | | | \
@@ -76,6 +76,10 @@
/*************************************************************************
MACROS
*************************************************************************/
/* For an easy Library Version Management */
#define RC_SEQ_LIB_VERSION 2
#define RC_SEQ_LIB_REVISION 1
#define STR(s) #s
#define MAKE_TEXT_VER_REV(Ver,Rev) (char*)(STR(Ver)"."STR(Rev))
@@ -123,12 +127,12 @@ Pos 0 1 2 3 4
1000us 2000us (Typical Pulse Width values)
*/
#define ACTIVE_AREA_STEP_NBR 3
#define INACTIVE_AREA_STEP_NBR 1
#define TOTAL_STEP_NBR(KeyNb,Type) ((Type==RC_CMD_STICK)?((KeyNb)*(ACTIVE_AREA_STEP_NBR+INACTIVE_AREA_STEP_NBR)):(((KeyNb)*(ACTIVE_AREA_STEP_NBR+INACTIVE_AREA_STEP_NBR))-1))
#define STEP(MinUs, MaxUs,KeyNb,Type) ((MaxUs-MinUs)/TOTAL_STEP_NBR(KeyNb,Type))
#define KEY_MIN_VAL(Idx,Step) ((ACTIVE_AREA_STEP_NBR+INACTIVE_AREA_STEP_NBR)*(Step)*(Idx))
#define KEY_MAX_VAL(Idx,Step) (KEY_MIN_VAL(Idx,Step)+(ACTIVE_AREA_STEP_NBR*(Step)))
#define ACTIVE_AREA_STEP_NBR 3
#define INACTIVE_AREA_STEP_NBR 1
#define TOTAL_STEP_NBR(KeyNb, Type) ((Type==RC_CMD_STICK)?((KeyNb)*(ACTIVE_AREA_STEP_NBR+INACTIVE_AREA_STEP_NBR)):(((KeyNb)*(ACTIVE_AREA_STEP_NBR+INACTIVE_AREA_STEP_NBR))-1))
#define STEP(MinUs, MaxUs, KeyNb, Type) ((MaxUs-MinUs)/TOTAL_STEP_NBR(KeyNb,Type))
#define KEY_MIN_VAL(Idx, Step) ((ACTIVE_AREA_STEP_NBR+INACTIVE_AREA_STEP_NBR)*(Step)*(Idx))
#define KEY_MAX_VAL(Idx, Step) (KEY_MIN_VAL(Idx,Step)+(ACTIVE_AREA_STEP_NBR*(Step)))
typedef struct {
int8_t InProgress;
@@ -138,6 +142,9 @@ typedef struct {
void *TableOrShortAction;
uint8_t SequenceLength;
uint8_t ShortActionMap;
#ifdef RC_SEQ_CONTROL_SUPPORT
uint8_t(*Control)(uint8_t Action, uint8_t SeqIdx);
#endif
}CmdSequenceSt_t;
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT
@@ -147,14 +154,14 @@ typedef struct {
}PosST_t;
typedef struct {
SoftRcPulseIn Pulse;
PosST_t Pos;
uint8_t Type; /* RC_CMD_STICK or RC_CMD_KEYBOARD or RC_CMD_CUSTOM */
uint8_t PosNb;
uint16_t PulseMinUs;
uint16_t PulseMaxUs;
uint16_t StepUs;
KeyMap_t *KeyMap;
SoftRcPulseIn Pulse;
PosST_t Pos;
uint8_t Type; /* RC_CMD_STICK or RC_CMD_KEYBOARD or RC_CMD_CUSTOM */
uint8_t PosNb;
uint16_t PulseMinUs;
uint16_t PulseMaxUs;
uint16_t StepUs;
const KeyMap_t *KeyMap;
}RcCmdSt_t;
#endif
@@ -175,47 +182,42 @@ static uint8_t CmdSignalNb;
static RcCmdSt_t RcChannel[RC_CMD_MAX_NB];
#endif
#ifdef RC_SEQ_WITH_STATIC_MEM_ALLOC_SUPPORT
#define AsMember .
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT
static ServoSt_t Servo[SERVO_MAX_NB];
#endif
static CmdSequenceSt_t CmdSequence[SEQUENCE_MAX_NB];
#else
#define AsMember ->
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT
static ServoSt_t **Servo=NULL;
static ServoSt_t *Servo = NULL;
#endif
static CmdSequenceSt_t **CmdSequence=NULL;
static CmdSequenceSt_t *CmdSequence = NULL;
#endif
/*************************************************************************
PRIVATE FUNCTION PROTOTYPES
*************************************************************************/
static void ExecuteSequence(uint8_t CmdIdx, uint8_t Pos);
#ifndef RC_SEQ_WITH_STATIC_MEM_ALLOC_SUPPORT
static void LoadSequenceOrShortAction(uint8_t CmdIdx,uint8_t Pos,void *SequenceOrShortAction, uint8_t SequenceLength);
#endif
static uint8_t ExecuteSequence(uint8_t CmdIdx, uint8_t Pos);
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT
static int8_t GetPos(uint8_t ChIdx,uint16_t PulseWidthUs);
static int8_t GetPos(uint8_t ChIdx, uint16_t PulseWidthUs);
#endif
//========================================================================================================================
void RcSeq_Init(void)
{
SeqNb=0;
ServoNb=0;
SeqNb = 0;
ServoNb = 0;
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT
for(uint8_t ChIdx=0;ChIdx<RC_CMD_MAX_NB;ChIdx++)
for(uint8_t ChIdx = 0; ChIdx < RC_CMD_MAX_NB; ChIdx++)
{
RcChannel[ChIdx].Pos.Idx=NO_POS;
RcChannel[ChIdx].Pos.Idx = NO_POS;
}
#endif
#ifdef RC_SEQ_WITH_STATIC_MEM_ALLOC_SUPPORT
for(uint8_t SeqIdx=0;SeqIdx<SEQUENCE_MAX_NB;SeqIdx++)
for(uint8_t SeqIdx = 0; SeqIdx < SEQUENCE_MAX_NB; SeqIdx++)
{
CmdSequence[SeqIdx].InProgress=0;
CmdSequence[SeqIdx].TableOrShortAction=NULL;
CmdSequence[SeqIdx].SequenceLength=0;
CmdSequence[SeqIdx].ShortActionMap=0;
CmdSequence[SeqIdx].InProgress = 0;
CmdSequence[SeqIdx].TableOrShortAction = NULL;
CmdSequence[SeqIdx].SequenceLength = 0;
CmdSequence[SeqIdx].ShortActionMap = 0;
}
#endif
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT
@@ -242,36 +244,53 @@ char *RcSeq_LibTextVersionRevision(void)
void RcSeq_DeclareServo(uint8_t Idx, uint8_t DigitalPin)
{
#ifdef RC_SEQ_WITH_STATIC_MEM_ALLOC_SUPPORT
if(Idx<SERVO_MAX_NB)
if(Idx < SERVO_MAX_NB)
{
Servo[Idx].Motor.attach(DigitalPin);
Servo[Idx].SeqLineInProgress=NO_SEQ_LINE;
if(ServoNb<(Idx+1)) ServoNb=(Idx+1);
Servo[Idx].SeqLineInProgress = NO_SEQ_LINE;
if(ServoNb < (Idx + 1)) ServoNb = (Idx + 1);
}
#else
if(Idx<SERVO_MAX_NB)
if(Idx < SERVO_MAX_NB)
{
ServoNb++;
if(!Servo) Servo=(ServoSt_t**)malloc(sizeof(ServoSt_t));
else Servo=(ServoSt_t**)realloc(Servo, sizeof(ServoSt_t)*ServoNb);
Servo[Idx] AsMember Motor.attach(DigitalPin);
Servo[Idx] AsMember SeqLineInProgress=NO_SEQ_LINE;
if(!Servo) Servo = (ServoSt_t*)malloc(sizeof(ServoSt_t));
else Servo = (ServoSt_t*)realloc(Servo, sizeof(ServoSt_t) * ServoNb);
Servo[Idx].Motor.attach(DigitalPin);
Servo[Idx].SeqLineInProgress = NO_SEQ_LINE;
}
#endif
}
//========================================================================================================================
void RcSeq_ServoWrite(uint8_t Idx, uint16_t Angle)
{
if(Idx < SERVO_MAX_NB)
{
Servo[Idx].Motor.write(Angle);
}
}
#endif
//========================================================================================================================
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT
void RcSeq_DeclareSignal(uint8_t Idx, uint8_t DigitalPin)
{
if(Idx<RC_CMD_MAX_NB)
if(Idx < RC_CMD_MAX_NB)
{
RcChannel[Idx].Pulse.attach(DigitalPin);
CmdSignalNb++;
}
}
//========================================================================================================================
void RcSeq_DeclareKeyboardOrStickOrCustom(uint8_t ChIdx, uint8_t Type, uint16_t PulseMinUs, uint16_t PulseMaxUs, KeyMap_t *KeyMap, uint8_t PosNb)
boolean RcSeq_SignalTimeout(uint8_t Idx, uint8_t TimeoutMs, uint8_t *State)
{
if(Idx < RC_CMD_MAX_NB)
{
return(RcChannel[Idx].Pulse.timeout(TimeoutMs, State));
}
return(0);
}
//========================================================================================================================
void RcSeq_DeclareKeyboardOrStickOrCustom(uint8_t ChIdx, uint8_t Type, uint16_t PulseMinUs, uint16_t PulseMaxUs, const KeyMap_t *KeyMap, uint8_t PosNb)
{
RcChannel[ChIdx].Type = Type;
RcChannel[ChIdx].PosNb = PosNb;
@@ -281,50 +300,62 @@ void RcSeq_DeclareKeyboardOrStickOrCustom(uint8_t ChIdx, uint8_t Type, uint16_t
RcChannel[ChIdx].KeyMap = KeyMap;
}
//========================================================================================================================
void RcSeq_DeclareCustomKeyboard(uint8_t ChIdx, KeyMap_t *KeyMapTbl, uint8_t KeyNb)
void RcSeq_DeclareCustomKeyboard(uint8_t ChIdx, const KeyMap_t *KeyMapTbl, uint8_t KeyNb)
{
RcSeq_DeclareKeyboardOrStickOrCustom(ChIdx, RC_CMD_CUSTOM, 0, 0, KeyMapTbl, KeyNb);
}
#endif
//========================================================================================================================
void RcSeq_DeclareCommandAndSequence(uint8_t CmdIdx,uint8_t Pos,SequenceSt_t *Table, uint8_t SequenceLength)
#ifdef RC_SEQ_CONTROL_SUPPORT
void RcSeq_DeclareCommandAndSequence(uint8_t CmdIdx,uint8_t Pos, const SequenceSt_t *Table, uint8_t SequenceLength, uint8_t(*Control)(uint8_t Action, uint8_t SeqIdx))
#else
void RcSeq_DeclareCommandAndSequence(uint8_t CmdIdx,uint8_t Pos, const SequenceSt_t *Table, uint8_t SequenceLength)
#endif
{
uint8_t Idx, ServoIdx;
uint16_t StartInDegrees;
uint32_t StartMinMs[SERVO_MAX_NB];
#ifdef RC_SEQ_WITH_STATIC_MEM_ALLOC_SUPPORT
for(Idx=0;Idx<SEQUENCE_MAX_NB;Idx++)
#ifndef RC_SEQ_WITH_STATIC_MEM_ALLOC_SUPPORT
if(!CmdSequence) CmdSequence = (CmdSequenceSt_t*)malloc(sizeof(CmdSequenceSt_t));
else CmdSequence = (CmdSequenceSt_t*)realloc(CmdSequence, sizeof(CmdSequenceSt_t) * (SeqNb + 1));
Idx = SeqNb;
SeqNb++;
#else
for(Idx = 0; Idx < SEQUENCE_MAX_NB; Idx++)
{
if(!CmdSequence[Idx].TableOrShortAction)
{
CmdSequence[Idx].CmdIdx=CmdIdx;
CmdSequence[Idx].Pos=Pos;
CmdSequence[Idx].TableOrShortAction=(void*)Table;
CmdSequence[Idx].SequenceLength=SequenceLength;
#endif
CmdSequence[Idx].CmdIdx = CmdIdx;
CmdSequence[Idx].Pos = Pos;
CmdSequence[Idx].TableOrShortAction = (void*)Table;
CmdSequence[Idx].SequenceLength = SequenceLength;
#ifdef RC_SEQ_CONTROL_SUPPORT
CmdSequence[Idx].Control = Control;
#endif
#ifdef RC_SEQ_WITH_STATIC_MEM_ALLOC_SUPPORT
SeqNb++;
break;
}
}
#else
LoadSequenceOrShortAction(CmdIdx,Pos,(void*)Table, SequenceLength);
#endif
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT
/* Get initial pulse width for each Servo */
for(Idx=0;Idx<SERVO_MAX_NB;Idx++)
for(Idx = 0; Idx < SERVO_MAX_NB; Idx++)
{
StartMinMs[Idx]=0xFFFFFFFF;
StartMinMs[Idx] = 0xFFFFFFFF;
}
for(Idx=0;Idx<SequenceLength;Idx++)
for(Idx = 0; Idx < SequenceLength; Idx++)
{
ServoIdx=(int8_t)PGM_READ_8(Table[Idx].ServoIndex);
if(ServoIdx!=255)
ServoIdx = (int8_t)PGM_READ_8(Table[Idx].ServoIndex);
if(ServoIdx != 255)
{
if((uint32_t)PGM_READ_32(Table[Idx].StartMotionOffsetMs)<=StartMinMs[ServoIdx])
if((uint32_t)PGM_READ_32(Table[Idx].StartMotionOffsetMs) <= StartMinMs[ServoIdx])
{
StartMinMs[ServoIdx]=(uint32_t)PGM_READ_32(Table[Idx].StartMotionOffsetMs);
StartInDegrees=(uint16_t)PGM_READ_8(Table[Idx].StartInDegrees);
Servo[ServoIdx] AsMember Motor.write(StartInDegrees);
StartMinMs[ServoIdx] = (uint32_t)PGM_READ_32(Table[Idx].StartMotionOffsetMs);
StartInDegrees = (uint16_t)PGM_READ_8(Table[Idx].StartInDegrees);
Servo[ServoIdx].Motor.write(StartInDegrees);
}
}
}
@@ -332,49 +363,42 @@ uint32_t StartMinMs[SERVO_MAX_NB];
}
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT
//========================================================================================================================
void RcSeq_DeclareCommandAndShortAction(uint8_t CmdIdx,uint8_t Pos,void(*ShortAction)(void))
void RcSeq_DeclareCommandAndShortAction(uint8_t CmdIdx, uint8_t Pos, void(*ShortAction)(void))
{
#ifdef RC_SEQ_WITH_STATIC_MEM_ALLOC_SUPPORT
uint8_t Idx;
for(Idx=0;Idx<SEQUENCE_MAX_NB;Idx++)
#ifndef RC_SEQ_WITH_STATIC_MEM_ALLOC_SUPPORT
if(!CmdSequence) CmdSequence = (CmdSequenceSt_t*)malloc(sizeof(CmdSequenceSt_t));
else CmdSequence = (CmdSequenceSt_t*)realloc(CmdSequence, sizeof(CmdSequenceSt_t) * (SeqNb + 1));
Idx = SeqNb;
SeqNb++;
#else
for(Idx = 0; Idx < SEQUENCE_MAX_NB; Idx++)
{
if(!CmdSequence[Idx].TableOrShortAction)
{
CmdSequence[Idx].CmdIdx=CmdIdx;
CmdSequence[Idx].Pos=Pos;
CmdSequence[Idx].TableOrShortAction=(void*)ShortAction;
#endif
CmdSequence[Idx].CmdIdx = CmdIdx;
CmdSequence[Idx].Pos = Pos;
CmdSequence[Idx].TableOrShortAction = (void*)ShortAction;
CmdSequence[Idx].SequenceLength = 0;
#ifdef RC_SEQ_WITH_STATIC_MEM_ALLOC_SUPPORT
SeqNb++;
break;
}
}
#else
LoadSequenceOrShortAction(CmdIdx,Pos,(void*)ShortAction, 0);
#endif
}
#endif
#ifndef RC_SEQ_WITH_STATIC_MEM_ALLOC_SUPPORT
static void LoadSequenceOrShortAction(uint8_t CmdIdx,uint8_t Pos,void *SequenceOrShortAction, uint8_t SequenceLength)
{
if(!CmdSequence) CmdSequence=(CmdSequenceSt_t**)malloc(sizeof(CmdSequenceSt_t));
else CmdSequence=(CmdSequenceSt_t**)realloc(CmdSequence,sizeof(CmdSequence)+sizeof(CmdSequenceSt_t));
CmdSequence[SeqNb] AsMember CmdIdx=CmdIdx;
CmdSequence[SeqNb] AsMember Pos=Pos;
CmdSequence[SeqNb] AsMember TableOrShortAction=(void*)SequenceOrShortAction;
CmdSequence[SeqNb] AsMember SequenceLength=SequenceLength;
SeqNb++;
}
#endif
//========================================================================================================================
uint8_t RcSeq_LaunchSequence(SequenceSt_t *Table)
uint8_t RcSeq_LaunchSequence(const SequenceSt_t *Table)
{
uint8_t Idx, Ret=0;
for(Idx=0;Idx<SEQUENCE_MAX_NB;Idx++)
uint8_t Idx, Ret = 0;
for(Idx = 0; Idx < SEQUENCE_MAX_NB; Idx++)
{
if(CmdSequence[Idx] AsMember TableOrShortAction==(void*)Table)
if(CmdSequence[Idx].TableOrShortAction == (void*)Table)
{
ExecuteSequence(CmdSequence[Idx] AsMember CmdIdx,CmdSequence[Idx] AsMember Pos);
Ret=1;
Ret = ExecuteSequence(CmdSequence[Idx].CmdIdx, CmdSequence[Idx].Pos);
break;
}
}
@@ -383,8 +407,8 @@ uint8_t Idx, Ret=0;
//========================================================================================================================
void RcSeq_Refresh(void)
{
static uint32_t NowMs=millis();
static uint32_t StartChronoInterPulseMs=millis();
static uint32_t NowMs = millis();
static uint32_t StartChronoInterPulseMs = millis();
SequenceSt_t *SequenceTable;
void (*ShortAction)(void);
int8_t ShortActionCnt;
@@ -398,100 +422,104 @@ int8_t CmdPos; /* Shall be signed */
uint32_t RcPulseWidthUs;
/* Asynchronous RC Command acquisition */
for(ChIdx=0;ChIdx<CmdSignalNb;ChIdx++)
for(ChIdx = 0; ChIdx < CmdSignalNb; ChIdx++)
{
if(!RcChannel[ChIdx].Pulse.available()) continue; /* Channel not used or no pulse received */
RcPulseWidthUs=RcChannel[ChIdx].Pulse.width_us();
CmdPos=GetPos(ChIdx,RcPulseWidthUs);
if(CmdPos>=0)
RcPulseWidthUs = RcChannel[ChIdx].Pulse.width_us();
CmdPos = GetPos(ChIdx, RcPulseWidthUs);
// Serial.print("W=");Serial.print(RcPulseWidthUs);Serial.print(" P=");Serial.println((int)CmdPos);
if(CmdPos >= 0)
{
if(RcChannel[ChIdx].Pos.Idx!=CmdPos)
if(RcChannel[ChIdx].Pos.Idx != CmdPos)
{
RcChannel[ChIdx].Pos.Idx=CmdPos;
RcChannel[ChIdx].Pos.StartChronoMs=millis();
RcChannel[ChIdx].Pos.Idx = CmdPos;
RcChannel[ChIdx].Pos.StartChronoMs = millis();
}
else
{
if((millis()-RcChannel[ChIdx].Pos.StartChronoMs)>=((RcChannel[ChIdx].Type==RC_CMD_STICK)?STICK_PULSE_CHECK_MS:KBD_PULSE_CHECK_MS)) /* Check the Pulse is valid at least for 100 ms or 50 ms */
if((millis() - RcChannel[ChIdx].Pos.StartChronoMs) >= ((RcChannel[ChIdx].Type == RC_CMD_STICK)?STICK_PULSE_CHECK_MS:KBD_PULSE_CHECK_MS)) /* Check the Pulse is valid at least for 100 ms or 50 ms */
{
ExecuteSequence(ChIdx,CmdPos);
RcChannel[ChIdx].Pos.Idx=NO_POS;
ExecuteSequence(ChIdx, CmdPos);
RcChannel[ChIdx].Pos.Idx = NO_POS;
}
}
}
else
{
RcChannel[ChIdx].Pos.Idx=NO_POS;
RcChannel[ChIdx].Pos.Idx = NO_POS;
}
}
#endif
NowMs=millis();
NowMs = millis();
if((NowMs - StartChronoInterPulseMs) >= 20UL)
{
/* We arrive here every 20 ms */
/* Asynchronous Servo Sequence management */
for(int8_t Idx=0;Idx<SeqNb;Idx++)
for(int8_t Idx = 0; Idx < SeqNb; Idx++)
{
if(!CmdSequence[Idx] AsMember InProgress || !CmdSequence[Idx] AsMember SequenceLength) continue;
ShortActionCnt=-1;
for(int8_t SeqLine=0;SeqLine<CmdSequence[Idx] AsMember SequenceLength;SeqLine++) /* Read all lines of the sequence table: this allows to run several servos simultaneously (not forcibly one after the other) */
if(!CmdSequence[Idx].InProgress || !CmdSequence[Idx].SequenceLength) continue;
ShortActionCnt = -1;
for(int8_t SeqLine = 0; SeqLine < CmdSequence[Idx].SequenceLength; SeqLine++) /* Read all lines of the sequence table: this allows to run several servos simultaneously (not forcibly one after the other) */
{
SequenceTable=(SequenceSt_t *)CmdSequence[Idx] AsMember TableOrShortAction;
ServoIdx=(int8_t)PGM_READ_8(SequenceTable[SeqLine].ServoIndex);
SequenceTable = (SequenceSt_t *)CmdSequence[Idx].TableOrShortAction;
ServoIdx = (int8_t)PGM_READ_8(SequenceTable[SeqLine].ServoIndex);
#ifdef RC_SEQ_WITH_SHORT_ACTION_SUPPORT
if(ServoIdx==255) /* Not a Servo: it's a short Action to perform only if not already done */
if(ServoIdx == 255) /* Not a Servo: it's a short Action to perform only if not already done */
{
ShortActionCnt++;
StartOfSeqMs = CmdSequence[Idx] AsMember StartChronoMs + (int32_t)PGM_READ_32(SequenceTable[SeqLine].StartMotionOffsetMs);
if( (NowMs>=StartOfSeqMs) && !TST_BIT(CmdSequence[Idx] AsMember ShortActionMap,ShortActionCnt) )
StartOfSeqMs = CmdSequence[Idx].StartChronoMs + (int32_t)PGM_READ_32(SequenceTable[SeqLine].StartMotionOffsetMs);
if( (NowMs >= StartOfSeqMs) && !TST_BIT(CmdSequence[Idx].ShortActionMap, ShortActionCnt) )
{
ShortAction=(void(*)(void))PGM_READ_16(SequenceTable[SeqLine].ShortAction);
ShortAction = (void(*)(void))PGM_READ_16(SequenceTable[SeqLine].ShortAction);
ShortAction();
SET_BIT(CmdSequence[Idx] AsMember ShortActionMap,ShortActionCnt); /* Mark short Action as performed */
/* If the last line contains an Action AsMember End of Sequence */
if(SeqLine==(CmdSequence[Idx] AsMember SequenceLength-1))
SET_BIT(CmdSequence[Idx].ShortActionMap, ShortActionCnt); /* Mark short Action as performed */
/* If the last line contains an Action: End of Sequence */
if(SeqLine == (CmdSequence[Idx].SequenceLength - 1))
{
CmdSequence[Idx] AsMember InProgress=0;
CmdSequence[Idx] AsMember ShortActionMap=0; /* Mark all Short Action as not performed */
CmdSequence[Idx].InProgress = 0;
CmdSequence[Idx].ShortActionMap = 0; /* Mark all Short Action as not performed */
}
}
continue;
}
#endif
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT
if(Servo[ServoIdx] AsMember RefreshNb && SeqLine!=Servo[ServoIdx] AsMember SeqLineInProgress)
if(Servo[ServoIdx].RefreshNb && SeqLine != Servo[ServoIdx].SeqLineInProgress)
{
continue;
}
StartOfSeqMs = CmdSequence[Idx] AsMember StartChronoMs + (int32_t)PGM_READ_32(SequenceTable[SeqLine].StartMotionOffsetMs);
StartOfSeqMs = CmdSequence[Idx].StartChronoMs + (int32_t)PGM_READ_32(SequenceTable[SeqLine].StartMotionOffsetMs);
MotionDurationMs = (int32_t)PGM_READ_32(SequenceTable[SeqLine].MotionDurationMs);
EndOfSeqMs = StartOfSeqMs + MotionDurationMs;
if(!Servo[ServoIdx] AsMember RefreshNb && Servo[ServoIdx] AsMember SeqLineInProgress==NO_SEQ_LINE)
if(!Servo[ServoIdx].RefreshNb && Servo[ServoIdx].SeqLineInProgress == NO_SEQ_LINE)
{
if( (NowMs>=StartOfSeqMs) && (NowMs<=EndOfSeqMs) )
if( (NowMs >= StartOfSeqMs) && (NowMs <= EndOfSeqMs) )
{
Servo[ServoIdx] AsMember SeqLineInProgress=SeqLine;
StartInDegrees=(uint16_t)PGM_READ_8(SequenceTable[SeqLine].StartInDegrees);
Servo[ServoIdx] AsMember RefreshNb=REFRESH_NB(MotionDurationMs);
Servo[ServoIdx] AsMember Motor.write(StartInDegrees);
Servo[ServoIdx].SeqLineInProgress = SeqLine;
StartInDegrees = (uint16_t)PGM_READ_8(SequenceTable[SeqLine].StartInDegrees);
Servo[ServoIdx].RefreshNb = REFRESH_NB(MotionDurationMs);
Servo[ServoIdx].Motor.write(StartInDegrees);
}
}
else
{
/* A sequence line is in progress: update the next position */
if(Servo[ServoIdx] AsMember RefreshNb) Servo[ServoIdx] AsMember RefreshNb--;
StartInDegrees=(uint16_t)PGM_READ_8(SequenceTable[SeqLine].StartInDegrees);
EndInDegrees=(uint16_t)PGM_READ_8(SequenceTable[SeqLine].EndInDegrees);
Pos=(int32_t)EndInDegrees-((int32_t)Servo[ServoIdx] AsMember RefreshNb*STEP_IN_DEGREES_PER_REFRESH((int32_t)StartInDegrees,(int32_t)EndInDegrees,(int32_t)MotionDurationMs)); //For refresh max nb, Pos = StartInDegrees
Servo[ServoIdx] AsMember Motor.write(Pos);
if( !Servo[ServoIdx] AsMember RefreshNb )
if(Servo[ServoIdx].RefreshNb) Servo[ServoIdx].RefreshNb--;
StartInDegrees = (uint16_t)PGM_READ_8(SequenceTable[SeqLine].StartInDegrees);
EndInDegrees = (uint16_t)PGM_READ_8(SequenceTable[SeqLine].EndInDegrees);
Pos = (int32_t)EndInDegrees - ((int32_t)Servo[ServoIdx].RefreshNb * STEP_IN_DEGREES_PER_REFRESH((int32_t)StartInDegrees,(int32_t)EndInDegrees,(int32_t)MotionDurationMs)); //For refresh max nb, Pos = StartInDegrees
Servo[ServoIdx].Motor.write(Pos);
if( !Servo[ServoIdx].RefreshNb )
{
Servo[ServoIdx] AsMember SeqLineInProgress=NO_SEQ_LINE;
Servo[ServoIdx].SeqLineInProgress = NO_SEQ_LINE;
/* Last servo motion and refresh = 0 -> End of Sequence */
if(SeqLine==(CmdSequence[Idx] AsMember SequenceLength-1))
if(SeqLine == (CmdSequence[Idx].SequenceLength - 1))
{
CmdSequence[Idx] AsMember InProgress=0;
CmdSequence[Idx] AsMember ShortActionMap=0; /* Mark all Short Action as not performed */
CmdSequence[Idx].InProgress = 0;
CmdSequence[Idx].ShortActionMap = 0; /* Mark all Short Action as not performed */
#ifdef RC_SEQ_CONTROL_SUPPORT
if(CmdSequence[Idx].Control != NULL) CmdSequence[Idx].Control(RC_SEQ_END_OF_SEQ, Idx);
#endif
}
}
}
@@ -501,76 +529,94 @@ uint32_t RcPulseWidthUs;
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT
SoftRcPulseOut::refresh(1); /* Force Refresh */
#endif
StartChronoInterPulseMs=millis();
StartChronoInterPulseMs = millis();
}
}
//========================================================================================================================
// PRIVATE FUNCTIONS
//========================================================================================================================
static void ExecuteSequence(uint8_t CmdIdx, uint8_t Pos)
static uint8_t ExecuteSequence(uint8_t CmdIdx, uint8_t Pos)
{
void(*ShortAction)(void);
uint8_t Idx;
uint8_t Idx, Ret = 0;
for(Idx=0;Idx<SeqNb;Idx++)
for(Idx = 0; Idx < SeqNb; Idx++)
{
if((CmdSequence[Idx] AsMember CmdIdx==CmdIdx) && (CmdSequence[Idx] AsMember Pos==Pos))
if((CmdSequence[Idx].CmdIdx == CmdIdx) && (CmdSequence[Idx].Pos == Pos))
{
#ifdef RC_SEQ_WITH_SHORT_ACTION_SUPPORT
if(CmdSequence[Idx] AsMember TableOrShortAction && !CmdSequence[Idx] AsMember SequenceLength)
if(CmdSequence[Idx].TableOrShortAction && !CmdSequence[Idx].SequenceLength)
{
/* It's a short action */
ShortAction=(void(*)(void))CmdSequence[Idx] AsMember TableOrShortAction;
ShortAction = (void(*)(void))CmdSequence[Idx].TableOrShortAction;
ShortAction();
Ret = 1;
}
else
#endif
{
/* It's a Table of Sequence */
if(!CmdSequence[Idx] AsMember InProgress)
if(!CmdSequence[Idx].InProgress)
{
CmdSequence[Idx] AsMember InProgress=1;
CmdSequence[Idx] AsMember StartChronoMs=millis();
#ifdef RC_SEQ_CONTROL_SUPPORT
uint8_t Go = 1;
if(CmdSequence[Idx].Control != NULL)
{
Go = CmdSequence[Idx].Control(RC_SEQ_START_CONDITION, Idx);
// Serial.print(F("Go for Seq["));Serial.print(Idx);Serial.print(F("] "));Serial.println(Go?F("Yes"):F("No"));
}
if(Go)
{
CmdSequence[Idx].InProgress = 1;
CmdSequence[Idx].StartChronoMs = millis();
Ret = 1;
}
#else
CmdSequence[Idx].InProgress = 1;
CmdSequence[Idx].StartChronoMs = millis();
Ret = 1;
#endif
}
}
break;
}
}
return(Ret);
}
//========================================================================================================================
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT
static int8_t GetPos(uint8_t ChIdx,uint16_t PulseWidthUs)
static int8_t GetPos(uint8_t ChIdx, uint16_t PulseWidthUs)
{
int8_t Idx, Ret=-1;
uint16_t PulseMinUs,PulseMaxUs;
int8_t Idx, Ret = -1;
uint16_t PulseMinUs, PulseMaxUs;
for(Idx=0;Idx<RcChannel[ChIdx].PosNb;Idx++)
for(Idx = 0; Idx < RcChannel[ChIdx].PosNb; Idx++)
{
switch(RcChannel[ChIdx].Type)
{
case RC_CMD_STICK: /* No break: normal */
case RC_CMD_MULTI_POS_SW:
if( (RcChannel[ChIdx].Type==RC_CMD_MULTI_POS_SW) || ((RcChannel[ChIdx].Type==RC_CMD_STICK) && (Idx<(RcChannel[ChIdx].PosNb/2))) )
if( (RcChannel[ChIdx].Type == RC_CMD_MULTI_POS_SW) || ((RcChannel[ChIdx].Type == RC_CMD_STICK) && (Idx < (RcChannel[ChIdx].PosNb / 2))) )
{
PulseMinUs=RcChannel[ChIdx].PulseMinUs+KEY_MIN_VAL(Idx,RcChannel[ChIdx].StepUs);
PulseMaxUs=RcChannel[ChIdx].PulseMinUs+KEY_MAX_VAL(Idx,RcChannel[ChIdx].StepUs);
PulseMinUs = RcChannel[ChIdx].PulseMinUs + KEY_MIN_VAL(Idx,RcChannel[ChIdx].StepUs);
PulseMaxUs = RcChannel[ChIdx].PulseMinUs + KEY_MAX_VAL(Idx,RcChannel[ChIdx].StepUs);
}
else
{
PulseMinUs=RcChannel[ChIdx].PulseMaxUs-KEY_MAX_VAL(RcChannel[ChIdx].PosNb-1-Idx,RcChannel[ChIdx].StepUs);
PulseMaxUs=RcChannel[ChIdx].PulseMaxUs-KEY_MIN_VAL(RcChannel[ChIdx].PosNb-1-Idx,RcChannel[ChIdx].StepUs);
PulseMinUs = RcChannel[ChIdx].PulseMaxUs - KEY_MAX_VAL(RcChannel[ChIdx].PosNb - 1 - Idx, RcChannel[ChIdx].StepUs);
PulseMaxUs = RcChannel[ChIdx].PulseMaxUs - KEY_MIN_VAL(RcChannel[ChIdx].PosNb - 1 - Idx, RcChannel[ChIdx].StepUs);
}
break;
case RC_CMD_CUSTOM:
PulseMinUs=(uint16_t)PGM_READ_16(RcChannel[ChIdx].KeyMap[Idx].Min);
PulseMaxUs=(uint16_t)PGM_READ_16(RcChannel[ChIdx].KeyMap[Idx].Max);
PulseMinUs = (uint16_t)PGM_READ_16(RcChannel[ChIdx].KeyMap[Idx].Min);
PulseMaxUs = (uint16_t)PGM_READ_16(RcChannel[ChIdx].KeyMap[Idx].Max);
break;
}
if((PulseWidthUs>=PulseMinUs) && (PulseWidthUs<=PulseMaxUs))
if((PulseWidthUs >= PulseMinUs) && (PulseWidthUs <= PulseMaxUs))
{
Ret=Idx;
Ret = Idx;
break;
}
}

View File

@@ -2,7 +2,7 @@
#define RC_SEQ_H
/*
English: by RC Navy (2012/2013)
English: by RC Navy (2012-2015)
=======
<RcSeq> is an asynchronous library for ATmega328P (UNO), ATtiny84 and ATtiny85 to easily create servo's sequences and/or to execute short actions from RC commands.
It can also be used to trig some short "actions" (the duration must be less than 20ms to not disturb the servo commands)
@@ -23,7 +23,7 @@
CAUTION: the end user shall also use asynchronous programmation method in the loop() function (no blocking functions such as delay() or pulseIn()).
http://p.loussouarn.free.fr
Francais: par RC Navy (2012/2013)
Francais: par RC Navy (2012-2015)
========
<RcSeq> est une librairie asynchrone pour ATmega328P (UNO), ATtiny84 et ATtiny85 pour creer facilement des sequences de servos et/ou executer des actions depuis des commandes RC.
Elle peut egalement etre utilisee pour lancer des "actions courtes" (la duree doit etre inferieure a 20ms pour ne pas perturber la commande des servos)
@@ -48,19 +48,17 @@
/* RCSEQ LIBRARY CONFIGURATION */
/**********************************************/
#define RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT /* Comment this line if you use <DigiUSB> library in your sketch */
//#define RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT /* Uncomment this if you use <SoftRcPulseOut> library in your sketch for servos and ESC */
#define RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT /* Uncomment this if you use <SoftRcPulseOut> library in your sketch for servos and ESC */
#define RC_SEQ_WITH_SHORT_ACTION_SUPPORT /* Uncomment this to allows to put call to short action in sequence table */
#define RC_SEQ_CONTROL_SUPPORT /* Uncomment this to allow control on sequences: start condition and end of sequence */
/**********************************************/
/* /!\ Do not touch below /!\ */
/**********************************************/
/* For an easy Library Version Management */
#define RC_SEQ_LIB_VERSION 2
#define RC_SEQ_LIB_REVISION 0
#define RC_SEQ_WITH_STATIC_MEM_ALLOC_SUPPORT /* Do NOT comment this line for DigiSpark, but you can for UNO */
#define RC_SEQ_WITH_STATIC_MEM_ALLOC_SUPPORT /* Do NOT comment this line for now: still buggy (to do: fix this) */
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT
#include <TinyPinChange.h>
@@ -86,14 +84,26 @@
#include <inttypes.h>
#include <stdio.h>
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT
#define SERVO_MAX_NB 10
#define SEQUENCE_MAX_NB 8
#define RC_CMD_MAX_NB 4
#if defined(RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT)
#if defined(__AVR_ATtiny85__)
#define SERVO_MAX_NB 3 /* 3 is the maximum for DigiSpark if DigiUSB is used in the skecth */
#else
#if (defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny167__))
#define SERVO_MAX_NB 6
#else
#define SERVO_MAX_NB 10
#endif
#endif
#else
#define SERVO_MAX_NB 3 /* 3 is the maximum for DigiSpark if DigiUSB is used in the skecth */
#define SEQUENCE_MAX_NB 1 /* 1 is the maximum for DigiSpark if DigiUSB is used in the skecth */
#define RC_CMD_MAX_NB 0
#define SERVO_MAX_NB 0
#endif
#if (defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny167__))
#define SEQUENCE_MAX_NB 4 /* 2 is the maximum for DigiSpark if DigiUSB is used in the skecth */
#define RC_CMD_MAX_NB 2
#else
#define SEQUENCE_MAX_NB 10
#define RC_CMD_MAX_NB 4
#endif
typedef struct {
@@ -122,7 +132,7 @@ typedef struct {
#define MOTION_WITHOUT_SOFT_START_AND_STOP(ServoIndex,StartInDegrees,EndInDegrees,StartMvtOffsetMs,MvtDurationMs) \
{ServoIndex, StartInDegrees, EndInDegrees, StartMvtOffsetMs, MvtDurationMs, NULL},
/* Macro to declare a short action (to use in "Sequence[]" structure table) */
/* Macro to declare a short action (to be used in "Sequence[]" structure table) */
#define SHORT_ACTION_TO_PERFORM(ShortAction, StartActionOffsetMs) {255, 0, 0, (StartActionOffsetMs), 0L, (ShortAction)},
enum {RC_CMD_STICK=0, RC_CMD_MULTI_POS_SW, RC_CMD_CUSTOM};
@@ -138,20 +148,27 @@ uint8_t RcSeq_LibRevision(void);
char *RcSeq_LibTextVersionRevision(void);
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT
void RcSeq_DeclareServo(uint8_t Idx, uint8_t DigitalPin);
void RcSeq_ServoWrite(uint8_t Idx, uint16_t Angle);
#endif
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT
void RcSeq_DeclareSignal(uint8_t Idx, uint8_t DigitalPin);
void RcSeq_DeclareKeyboardOrStickOrCustom(uint8_t ChIdx, uint8_t Type, uint16_t PulseMinUs, uint16_t PulseMaxUs, KeyMap_t *KeyMapTbl, uint8_t PosNb);
void RcSeq_DeclareCustomKeyboard(uint8_t ChIdx, KeyMap_t *KeyMapTbl, uint8_t PosNb);
boolean RcSeq_SignalTimeout(uint8_t Idx, uint8_t TimeoutMs, uint8_t *State);
void RcSeq_DeclareKeyboardOrStickOrCustom(uint8_t ChIdx, uint8_t Type, uint16_t PulseMinUs, uint16_t PulseMaxUs, const KeyMap_t *KeyMapTbl, uint8_t PosNb);
void RcSeq_DeclareCustomKeyboard(uint8_t ChIdx, const KeyMap_t *KeyMapTbl, uint8_t PosNb);
#define RcSeq_DeclareStick(ChIdx, PulseMinUs, PulseMaxUs, PosNb) RcSeq_DeclareKeyboardOrStickOrCustom(ChIdx, RC_CMD_STICK, PulseMinUs, PulseMaxUs, NULL, PosNb)
#define RcSeq_DeclareMultiPosSwitch(ChIdx, PulseMinUs, PulseMaxUs, PosNb) RcSeq_DeclareKeyboardOrStickOrCustom(ChIdx, RC_CMD_MULTI_POS_SW, PulseMinUs, PulseMaxUs, NULL, PosNb)
#define RcSeq_DeclareKeyboard(ChIdx, PulseMinUs, PulseMaxUs, KeyNb) RcSeq_DeclareKeyboardOrStickOrCustom(ChIdx, RC_CMD_MULTI_POS_SW, PulseMinUs, PulseMaxUs, NULL, KeyNb)
#ifdef RC_SEQ_WITH_SHORT_ACTION_SUPPORT
void RcSeq_DeclareCommandAndShortAction(uint8_t CmdIdx,uint8_t TypeCmd,void(*ShortAction)(void));
void RcSeq_DeclareCommandAndShortAction(uint8_t CmdIdx, uint8_t TypeCmd, void(*ShortAction)(void));
#endif
#endif
void RcSeq_DeclareCommandAndSequence(uint8_t CmdIdx,uint8_t TypeCmd,SequenceSt_t *Table, uint8_t SequenceLength);
uint8_t RcSeq_LaunchSequence(SequenceSt_t *Table);
#ifdef RC_SEQ_CONTROL_SUPPORT
void RcSeq_DeclareCommandAndSequence(uint8_t CmdIdx, uint8_t TypeCmd, const SequenceSt_t *Table, uint8_t SequenceLength, uint8_t(*Control)(uint8_t Action, uint8_t CmdSeqIdx));
enum {RC_SEQ_START_CONDITION, RC_SEQ_END_OF_SEQ};
#else
void RcSeq_DeclareCommandAndSequence(uint8_t CmdIdx, uint8_t TypeCmd, const SequenceSt_t *Table, uint8_t SequenceLength);
#endif
uint8_t RcSeq_LaunchSequence(const SequenceSt_t *Table);
#ifdef RC_SEQ_WITH_SHORT_ACTION_SUPPORT
#define RcSeq_LaunchShortAction(ShortAction) if(ShortAction) ShortAction()
#endif
@@ -162,25 +179,28 @@ void RcSeq_Refresh(void);
/*******************************************************/
/* Macro en Francais de declaration mouvement English native Macro to declare a motion */
#define MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS MOTION_WITH_SOFT_START_AND_STOP
#define MVT_SANS_DEBUT_ET_FIN_MVT_LENTS MOTION_WITHOUT_SOFT_START_AND_STOP
#define ACTION_COURTE_A_EFFECTUER SHORT_ACTION_TO_PERFORM
#define MVT_AVEC_DEBUT_ET_FIN_MVT_LENTS MOTION_WITH_SOFT_START_AND_STOP
#define MVT_SANS_DEBUT_ET_FIN_MVT_LENTS MOTION_WITHOUT_SOFT_START_AND_STOP
#define ACTION_COURTE_A_EFFECTUER SHORT_ACTION_TO_PERFORM
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT
#define RC_CLAVIER_MAISON RC_CUSTOM_KEYBOARD
#define VALEUR_CENTRALE_US CENTER_VALUE_US
#define RC_CLAVIER_MAISON RC_CUSTOM_KEYBOARD
#define VALEUR_CENTRALE_US CENTER_VALUE_US
#endif
#ifdef RC_SEQ_CONTROL_SUPPORT
#define RC_SEQ_CONDITION_DE_DEPART RC_SEQ_START_CONDITION
#define RC_SEQ_FIN_DE_SEQ RC_SEQ_END_OF_SEQ
#endif
/* Methodes en Francais English native methods */
#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT
#define RcSeq_DeclareManche RcSeq_DeclareStick
#define RcSeq_DeclareClavier RcSeq_DeclareKeyboard
#define RcSeq_DeclareClavierMaison RcSeq_DeclareCustomKeyboard
#define RcSeq_DeclareInterMultiPos RcSeq_DeclareMultiPosSwitch
#define RcSeq_DeclareCommandeEtActionCourte RcSeq_DeclareCommandAndShortAction
#define RcSeq_DeclareManche RcSeq_DeclareStick
#define RcSeq_DeclareClavier RcSeq_DeclareKeyboard
#define RcSeq_DeclareClavierMaison RcSeq_DeclareCustomKeyboard
#define RcSeq_DeclareInterMultiPos RcSeq_DeclareMultiPosSwitch
#define RcSeq_DeclareCommandeEtActionCourte RcSeq_DeclareCommandAndShortAction
#endif
#define RcSeq_DeclareCommandeEtSequence RcSeq_DeclareCommandAndSequence
#define RcSeq_LanceSequence RcSeq_LaunchSequence
#define RcSeq_LanceActionCourte RcSeq_LaunchShortAction
#define RcSeq_Rafraichit RcSeq_Refresh
#define RcSeq_DeclareCommandeEtSequence RcSeq_DeclareCommandAndSequence
#define RcSeq_LanceSequence RcSeq_LaunchSequence
#define RcSeq_LanceActionCourte RcSeq_LaunchShortAction
#define RcSeq_Rafraichit RcSeq_Refresh
#endif

View File

@@ -0,0 +1,116 @@
RcSeq library
=============
**RcSeq** is an asynchronous library for ATmega328P (**UNO**), ATmega2560 (**MEGA**), ATtiny84, ATtiny85 (**Digispark**) and ATtiny167 (**Digispark pro**) to easily create **servo's sequences** and/or to execute **short actions** from RC commands, from a digital input, or from a launch function called in the sketch.
The **A**pplication **P**rogramming **I**nterface (**API**) makes **RcSeq** library very easy to use.
Some definitions:
----------------
* **Sequence**: is used to sequence one or several servos (sequence is defined in a structure in the user's sketch to be performed when the RC command rises). The Sequence table (structure) may contain some servo motions and some short actions to call at a predefined time. For each servo, start angle, end angle and speed are tunable.
* **Short Action**: is used to perform a quick action (action is a short function defined in the user's sketch to be called when the RC command rises). The duration must be less than 20ms to not disturb the servo commands.
Some examples of use cases:
--------------------------
* **A landing gear retract:**
* Lock, door and leg servos sequenced with a single RC channel
* from a predefined position of the stick on the transmitter
* from the 2 positions "Aux Channel" of the transmitter
* **Navigation lights for aircraft:**
* Anticollision, beacon, landing lights commanded:
* from predefined positions of the stick on the transmitter
* from push-buttons in place of the stick potentiometer
* **Multi-switch:**
* Up to 8 digital pins driven from a single RC channel
* using the stick of the transmitter
* using 8 push-buttons in place of the stick potentiometer
* **Zodiac animation:**
* A pneumatic Zodiac dropped at sea and lifted back to the deck of a ship. Drop and lift sequences commanded:
* from predefined positions of the stick on the transmitter
* from a regular ON/OFF switch (for demo on table without RC set)
* **Animatronics sequences:**
* leg motion,
* mouth motion,
* eyes motion,
* etc.
Triggers:
--------
**Sequences** and **short actions** can be trigged by:
* a RC signal (eg: RC receiver output)
* from one or several **predefined positions of a stick** of the transmitter
* from one or several **push-button** (keyboard) replacing a a stick of the transmitter. (**RcSeq** assumes Push-Buttons associated Pulse duration are equidistant).
* from **Custom Keyboard** replacing a stick of the the transmitter. (The pulse durations can be defined independently for each Push-Button).
* from **Multi position switch** (2 pos switch, 3 pos switch, or more, eg. rotactor) replacing a stick of the the transmitter.
* a regular ON/OFF switch (no RC set required).
* a launch function call in the sketch.
API/methods:
-----------
* RcSeq_Init()
* RcSeq_DeclareSignal()
* RcSeq_DeclareStick()
* RcSeq_DeclareKeyboard()
* RcSeq_DeclareCustomKeyboard()
* RcSeq_DeclareMultiPosSwitch()
* RcSeq_SignalTimeout()
* RcSeq_DeclareServo()
* RcSeq_DeclareCommandAndSequence()
* RcSeq_DeclareCommandAndShortAction()
* RcSeq_LaunchSequence()
* RcSeq_LaunchShortAction()
* RcSeq_Refresh()
* RcSeq_LibVersion()
* RcSeq_LibRevision()
* RcSeq_LibTextVersionRevision()
Macros and constants:
--------------------
* const SequenceSt_t
* const KeyMap_t
* RC_SEQUENCE()
* RC_CUSTOM_KEYBOARD()
* SHORT_ACTION_TO_PERFORM()
* MOTION_WITH_SOFT_START_AND_STOP()
* MOTION_WITHOUT_SOFT_START_AND_STOP()
* CENTER_VALUE_US
* RC_SEQ_START_CONDITION
* RC_SEQ_END_OF_SEQ
Design considerations:
---------------------
The **RcSeq** library requires 3 other libraries written by the same author:
1. **TinyPinChange**: a library to catch asynchronously the input change using Pin Change Interruption capability of the AVR microcontroller.
2. **SoftRcPulseIn**: a library to catch asynchronously the input pulses using **TinyPinChange** library.
3. **SoftRcPulseOut**: a library mainly based on the **SoftwareServo** library, but with a better pulse generation to limit jitter and with some other enhancements.
CAUTION:
-------
The end user shall also use asynchronous programmation method in the loop() function (no blocking functions such as delay() or pulseIn()).
Contact
-------
If you have some ideas of enhancement, please contact me by clicking on: [RC Navy](http://p.loussouarn.free.fr/contact.html).

View File

@@ -15,11 +15,13 @@ RcSeq_LibRevision KEYWORD2
RcSeq_LibTextVersionRevision KEYWORD2
RcSeq_Init KEYWORD2
RcSeq_DeclareSignal KEYWORD2
RcSeq_SignalTimeout KEYWORD2
RcSeq_DeclareKeyboard KEYWORD2
RcSeq_DeclareClavier KEYWORD2
RcSeq_DeclareStick KEYWORD2
RcSeq_DeclareManche KEYWORD2
RcSeq_DeclareServo KEYWORD2
RcSeq_ServoWrite KEYWORD2
RcSeq_DeclareCustomKeyboard KEYWORD2
RcSeq_DeclareClavierMaison KEYWORD2
RcSeq_DeclareMultiPosSwitch KEYWORD2
@@ -51,3 +53,8 @@ RC_CLAVIER_MAISON LITERAL1
RC_SEQUENCE LITERAL1
CENTER_VALUE_US LITERAL1
VALEUR_CENTRALE_US LITERAL1
RC_SEQ_START_CONDITION LITERAL1
RC_SEQ_CONDITION_DE_DEPART LITERAL1
RC_SEQ_END_OF_SEQ LITERAL1
RC_SEQ_FIN_DE_SEQ LITERAL1