#ifndef RC_SEQ_H #define RC_SEQ_H /* English: by RC Navy (2012/2013) ======= 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) The Application Programming Interface (API) makes library very easy to use. needs 3 other libraries written by the same author: 1) : a library to catch asynchronously the input change using Pin Change Interruption capability of the AVR 2) : a library to catch asynchronously the input pulses using library 3) : a library mainly based on the library, but with a better pulse generation to limit jitter RC Signals (receiver outputs) can be assigned to a control type: -Stick Positions (up to 8, but in practice, 4 is the maximum to manually discriminate each stick position) -Multi position switch (2 pos switch, 3 pos switch, or more, eg. rotactor) -Keyboard ( assumes Push-Buttons associated Pulse duration are equidistant) -Custom Keyboard (The pulse durations can be defined independently for each Push-Button) 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. -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) 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) ======== 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) L'Interface de Programmation d'Application (API) fait que la librairie est tres facile a utiliser. necessite 3 autres librairies ecrites par le meme auteur: 1) : une librarie pour capter de maniere asynchrone les changements d'etat des broches utilisant les interruptions sur changement des pins des AVR 2) : une librarie pour capter de maniere asynchrone les impulsions entrantes en utilisant la librairie 3) : une librairie majoritairement basee sur la librairie , mais avec une meilleur generation des impulsions pour limiter la gigue Les signaux RC (sorties du recepteur) peuvent etre associes a un type de controle: -Positions de Manche (jusqu'a 8, mais en pratique, 4 est le maximum pour discriminer manuellement les positions du manche) -Interrupteur multi-positions (interrupteur 2 pos, interrupteur 3 pos, ou plus, ex. rotacteur) -Clavier ( suppose que les durees d'impulsion des Bouton-Poussoirs sont equidistantes) -Clavier "Maison" (Les durees d'impulsion peuvent etre definies de manière independante pour chaque Bouton-Poussoir) Quelques definitions: -Sequence: est utilisee pour sequencer un ou plusieurs servos (sequence est definie dans une structure dans le sketch utilisateur: est lancee quand la commande RC est recue) La table de sequence (structure) peut contenir des mouvements de servo et des actions courtes a appeler. -Action courte: est utilisee pour une action rapide (action est une fonction courte definie dans le sketch utilsateur: est appelee quand la commande RC est recue) ATTENTION: l'utilisateur final doit egalement utiliser la methode de programmation asynchrone dans la fonction loop() (pas de fonctions bloquantes comme delay() ou pulseIn()). http://p.loussouarn.free.fr */ /**********************************************/ /* RCSEQ LIBRARY CONFIGURATION */ /**********************************************/ #define RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT /* Comment this line if you use library in your sketch */ //#define RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT /* Uncomment this if you use 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 */ /**********************************************/ /* /!\ 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 */ #ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT #include #include #else #warning RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT disabled: no RC command possible!!! #endif #ifndef RC_SEQ_WITH_SHORT_ACTION_SUPPORT #warning RC_SEQ_WITH_SHORT_ACTION_SUPPORT disabled: no short action possible!!! #endif #ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT #include #else #warning RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT disabled: no Servo/ESC command possible!!! #endif #if defined(ARDUINO) && ARDUINO >= 100 #include "Arduino.h" #else #include "WProgram.h" #endif #include #include #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 #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 #endif typedef struct { uint8_t ServoIndex; uint8_t StartInDegrees; uint8_t EndInDegrees; uint32_t StartMotionOffsetMs; uint32_t MotionDurationMs; void (*ShortAction)(void); }SequenceSt_t; typedef struct { uint16_t Min; uint16_t Max; } KeyMap_t; #define TABLE_ITEM_NBR(Tbl) (sizeof(Tbl)/sizeof(Tbl[0])) /* Macro to declare a motion WITH soft start and soft stop (to use in "Sequence[]" structure table) */ #define MOTION_WITH_SOFT_START_AND_STOP(ServoIndex,StartInDegrees,EndInDegrees,StartMvtOffsetMs,MvtDurationMs,PourCent) \ {(ServoIndex), (StartInDegrees), (StartInDegrees+((EndInDegrees-StartInDegrees)*PourCent)/100L), (StartMvtOffsetMs), ((MvtDurationMs*2L*PourCent)/100L), NULL }, \ {(ServoIndex), (StartInDegrees+((EndInDegrees-StartInDegrees)*PourCent)/100L), (EndInDegrees-((EndInDegrees-StartInDegrees)*PourCent)/100L), (StartMvtOffsetMs+(MvtDurationMs*2L*PourCent)/100L), ((MvtDurationMs*(100L-4L*PourCent))/100L), NULL }, \ {(ServoIndex), (EndInDegrees-((EndInDegrees-StartInDegrees)*PourCent)/100L), (EndInDegrees), ((StartMvtOffsetMs+(MvtDurationMs*2L*PourCent)/100L)+(MvtDurationMs*(100L-4L*PourCent))/100L), ((MvtDurationMs*2L*PourCent)/100L), NULL }, /* Macro to declare a motion WITHOUT soft start and soft stop (to use in "Sequence[]" structure table) */ #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) */ #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}; #define RC_SEQUENCE(Sequence) Sequence, TABLE_ITEM_NBR(Sequence) #define RC_CUSTOM_KEYBOARD(KeyMap) KeyMap, TABLE_ITEM_NBR(KeyMap) #define CENTER_VALUE_US(CenterVal,Tol) ((CenterVal)-(Tol)),((CenterVal)+(Tol)) void RcSeq_Init(void); uint8_t RcSeq_LibVersion(void); 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); #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); #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)); #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_WITH_SHORT_ACTION_SUPPORT #define RcSeq_LaunchShortAction(ShortAction) if(ShortAction) ShortAction() #endif void RcSeq_Refresh(void); /*******************************************************/ /* Application Programming Interface (API) en Francais */ /*******************************************************/ /* 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 #ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT #define RC_CLAVIER_MAISON RC_CUSTOM_KEYBOARD #define VALEUR_CENTRALE_US CENTER_VALUE_US #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 #endif #define RcSeq_DeclareCommandeEtSequence RcSeq_DeclareCommandAndSequence #define RcSeq_LanceSequence RcSeq_LaunchSequence #define RcSeq_LanceActionCourte RcSeq_LaunchShortAction #define RcSeq_Rafraichit RcSeq_Refresh #endif