enhering

servo module

Sep 15th, 2017
153
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.46 KB | None | 0 0
  1. #ifndef SCM_H_
  2. #define SCM_H_
  3.  
  4.   #include "ModuleCapacityOptions.h"
  5.   #include "ModuleSelectOptions.h"
  6.  
  7.   #include "AVRBase.h"
  8.   #include "Blink.h"
  9.   #include "SPIProtocol.h"
  10.  
  11.   #define BOARD_BUILD     BUILD_NUMBER_STR
  12.  
  13.   #include "PCA9685.h"
  14.  
  15.   #define SERVO_TIMING_RANGE 4096
  16.   #define SERVOMIN_TIMING    150
  17.   #define SERVOMAX_TIMING    3500
  18.  
  19.   #define SERVO_COMMAND_MAX  10000
  20.   #define SERVO_COMMAND_MIN -10000
  21.  
  22.   #define NUM_SERVO_CHANNELS 16
  23.  
  24.   class SCM : public AVRBase {
  25.     public:
  26.       SCM();
  27.       ~SCM();
  28.  
  29.       void ManageSlaveSPIInterrupt();
  30.  
  31.       void SetOutputSelectorCallback(volatile bool (* pCallback)(uint8_t)) { m_cSPIProtocol.SetOutputSelectorCallback(pCallback); }
  32.       void SetInputSelectorCallback(volatile void (pCallback)(uint8_t))    { m_cSPIProtocol.SetInputSelectorCallback(pCallback);  }
  33.  
  34.       void Run();
  35.  
  36.       void CustomSetup();
  37.       void CustomLoop();
  38.  
  39.       bool OutputSelector(uint8_t);
  40.       void InputSelector(uint8_t);
  41.      
  42.       void SetServoPos(uint8_t, float);
  43.  
  44.     private:
  45.       SPIProtocol m_cSPIProtocol;
  46.       Blink m_cBlink;
  47.  
  48.       volatile uint8_t  m_nModuleStatus;
  49.       volatile uint32_t m_nModuleCapacities;
  50.       volatile uint8_t  m_eSystemStatus;
  51.       volatile uint8_t  m_eMissionStage;
  52.      
  53.       PCA9685 * m_pcPCA9685;
  54.  
  55.       // System data
  56.       int8_t m_nNumServoChannels;
  57.  
  58.       volatile int16_t m_anServoPos[NUMSERVOS];
  59.       volatile int16_t m_anServoZero[NUMSERVOS];
  60.       volatile int16_t m_anServoMax[NUMSERVOS];
  61.       volatile int16_t m_anServoMin[NUMSERVOS];
  62.       volatile bool    m_abServoEnable[NUMSERVOS];
  63.       volatile bool    m_abServoChanged[NUMSERVOS];
  64.       // volatile uint8_t m_anServoFrequency[NUMSERVOS];
  65.  
  66.       int16_t m_fServoRange;
  67.       uint8_t m_nSelectedServo;
  68.   };
  69.  
  70. #endif
  71.  
  72. #include "SCM.h"
  73.  
  74. SCM::SCM() {
  75.   m_nNumServoChannels = 16;
  76.   m_nModuleCapacities = BIT17_SERVO_CONTROLER;
  77.  
  78.   m_nModuleStatus = 0;
  79.   // sbi(m_nModuleStatus, MODULE_STATUS_BIT_NONZERO);
  80.  
  81.   m_nSelectedServo = 0;
  82.  
  83.   GPIO1_IS_OUTPUT;
  84.   GPIO1_HIGH;
  85.  
  86.   m_pcPCA9685 = new(PCA9685);
  87.  
  88.   m_pcPCA9685->Reset();
  89.  
  90.   m_pcPCA9685->SetPWMFreq(60);
  91.  
  92.   for (uint8_t nIndex = 0; nIndex < NUMSERVOS; nIndex++) {
  93.     m_anServoZero[nIndex] = 0;
  94.     m_anServoMax[nIndex] = SERVO_COMMAND_MAX;
  95.     m_anServoMin[nIndex] = SERVO_COMMAND_MIN;
  96.     m_anServoPos[nIndex] = SERVO_COMMAND_MIN;
  97.     m_abServoEnable[nIndex] = false;
  98.     m_abServoChanged[nIndex] = true;
  99.   }
  100.  
  101.   GPIO1_LOW; // PWM OUTPUT ENABLE
  102.  
  103.   m_cBlink.SetLEDGPIO(7);
  104.   m_cBlink.SetLEDOnCount(50000);
  105.   m_cBlink.SetLEDOffCount(50000);
  106.  
  107.   m_cBlink.BlinkLED();
  108. }
  109.  
  110. SCM::~SCM() {
  111.  
  112. }
  113.  
  114. void SCM::ManageSlaveSPIInterrupt() {
  115.   m_cSPIProtocol.ManageSlaveSPIInterrupt();
  116. }
  117.  
  118. void SCM::Run() {
  119.  
  120.   CustomSetup();
  121.  
  122.   while(1) {
  123.     m_cBlink.ManageLED();
  124.  
  125.     CustomLoop();  
  126.   }
  127. }
  128.  
  129. void SCM::CustomSetup() {
  130.   m_cSPIProtocol.RunAsSlave();
  131.   m_cSPIProtocol.InitSPI();
  132. }
  133.  
  134. void SCM::CustomLoop() {
  135.   uint8_t nServoNum;
  136.  
  137.   for (nServoNum = 0; nServoNum < NUM_SERVO_CHANNELS; nServoNum++) {
  138.     if (m_abServoChanged[nServoNum]) {
  139.       if (m_abServoEnable[nServoNum]) {
  140.         SetServoPos(nServoNum);
  141.       }
  142.       else {
  143.         m_anServoPos[nServoNum] = SERVO_COMMAND_MIN;
  144.         SetServoPos(nServoNum);
  145.       }
  146.       m_abServoChanged[nServoNum] = false;
  147.     }
  148.   }
  149. }
  150.  
  151. bool SCM::OutputSelector(uint8_t nSelect) {
  152.  
  153.   switch (nSelect) {
  154.     case B00_MODULE_STATUS: m_cSPIProtocol.SendByteViaSPI(NOT_APPLICABLE, NOT_APPLICABLE, (uint8_t) m_nModuleStatus);
  155.     case B00_SYSTEM_STATUS: m_cSPIProtocol.ExpectByte(); break;
  156.     case B00_MISSION_STAGE: m_cSPIProtocol.ExpectByte(); break;
  157.  
  158.     case B17_NUM_SERVO_CHANNELS: m_cSPIProtocol.SendByteViaSPI(NOT_APPLICABLE, NOT_APPLICABLE, m_nNumServoChannels);
  159.  
  160.     case B17_SERVO_SELECT: m_cSPIProtocol.ExpectByte(); break;
  161.  
  162.     case B17_SERVO_MIN:    m_cSPIProtocol.ExpectInt(); break;
  163.     case B17_SERVO_MAX:    m_cSPIProtocol.ExpectInt(); break;
  164.     case B17_SERVO_ZERO:   m_cSPIProtocol.ExpectInt(); break;
  165.     case B17_SERVO_POS:    m_cSPIProtocol.ExpectInt(); break;
  166.  
  167.     case B17_SERVO_ENABLE: m_cSPIProtocol.ExpectByte(); break;
  168.  
  169.     default: SPDR = NOT_UNDERSTOOD; return false;
  170.   }
  171.  
  172.   return true;
  173. }
  174.  
  175. void SCM::InputSelector(uint8_t nSelect) {
  176.  
  177.   switch (nSelect) {
  178.     case B00_SYSTEM_STATUS: m_eSystemStatus = m_cSPIProtocol.ReadByteViaSPI(NOT_APPLICABLE, NOT_APPLICABLE); break;
  179.     case B00_MISSION_STAGE: m_eMissionStage = m_cSPIProtocol.ReadByteViaSPI(NOT_APPLICABLE, NOT_APPLICABLE); break;
  180.  
  181.     case B17_SERVO_SELECT: m_nSelectedServo = m_cSPIProtocol.ReadByteViaSPI(NOT_APPLICABLE, NOT_APPLICABLE); break;
  182.  
  183.     case B17_SERVO_MIN:    m_nServoMin[m_nSelectedServo]    = m_cSPIProtocol.ReadLongViaSPI(NOT_APPLICABLE, NOT_APPLICABLE);
  184.                            m_abServoChanged[m_nSelectedServo] = true;
  185.                            break;
  186.  
  187.     case B17_SERVO_MAX:    m_nServoMax[m_nSelectedServo]    = m_cSPIProtocol.ReadLongViaSPI(NOT_APPLICABLE, NOT_APPLICABLE);
  188.                            m_abServoChanged[m_nSelectedServo] = true;
  189.                            break;
  190.     case B17_SERVO_ZERO:   m_nServoZero[m_nSelectedServo]   = m_cSPIProtocol.ReadLongViaSPI(NOT_APPLICABLE, NOT_APPLICABLE);
  191.                            m_abServoChanged[m_nSelectedServo] = true;
  192.                            break;
  193.     case B17_SERVO_POS:    m_nServoPos[m_nSelectedServo]    = m_cSPIProtocol.ReadLongViaSPI(NOT_APPLICABLE, NOT_APPLICABLE);
  194.                            m_abServoChanged[m_nSelectedServo] = true;
  195.                            break;
  196.     case B17_SERVO_ENABLE: m_nServoEnable[m_nSelectedServo] = m_cSPIProtocol.ReadByteViaSPI(NOT_APPLICABLE, NOT_APPLICABLE);
  197.                            m_abServoChanged[m_nSelectedServo] = true;
  198.                            break;
  199.  
  200.     default: SPDR = NOT_UNDERSTOOD;
  201.   }
  202. }
  203.  
  204. void SCM::SetServoPos(uint8_t nServoNum, int16_t nServoPos) {
  205.  
  206.   if (nServoNum < NUMSERVOS) {
  207.  
  208.     if (m_abServoEnable[nServoNum]) {
  209.  
  210.       uint16_t nServoOffTime;
  211.  
  212.       if (nServoPos < m_anServoMin[nServoNum]) {
  213.         nServoPos = m_anServoMin[nServoNum];
  214.       }
  215.  
  216.       if (nServoPos > m_anServoMax[nServoNum]) {
  217.         nServoPos = m_anServoMax[nServoNum];
  218.       }
  219.  
  220.       uint16_t nZeroPos = m_anServoZero[nServoNum];
  221.       uint16_t nPositiveRange = 4096 - nZeroPos;
  222.       uint16_t nNegativeRange = nZeroPos;
  223.  
  224.       if (nServoPos >= 0) {
  225.         nServoOffTime = (uint16_t) (fZeroPos + fServoPos * fPositiveRange);
  226.       }
  227.       else {
  228.         nServoOffTime = (uint16_t) (fZeroPos + fServoPos * fNegativeRange);
  229.       }
  230.  
  231.       m_pcPCA9685->SetPWM(nServoNum, 0, nServoOffTime);
  232.  
  233.       m_afServoPos[nServoNum] = nServoOffTime;
  234.     }
  235.   }
  236. }
Advertisement
Add Comment
Please, Sign In to add comment