View Single Post
Jun 11, 2012, 05:11 AM
Registered User
unisev's Avatar
Thread OP

Step 1


Here is the old version schema :



And the associated timeline :



This version is fully working, here is the non-cleaned & non-optimised code :

Code:
// Sketch to read a Rx receiver and to apply first channels to some servos
// V003
// Frome Sev

#define NO_PORTB_PINCHANGES //to go faster
#define NO_PORTC_PINCHANGES //to go faster

#include "PinChangeInt.h"

#include <Servo.h>

// LED pins
#define LEDPINO 13 //local Arduino PIN
#define LEDPINR 12 //RED LED for visible failsafe

// Parameters (total NBOFCH+NBOFSERVO can only be 10 MAX)
#define NBOFCH 6 // Put here the total Rx channel number and plug the FIRST channel on the PIN 2
#define NBOFSERVO 4 // Put here the total servo number and plug the FIRST one directely after the last Rx channel
#define FSCH 1 // This is the channel that will be survey for failsafe

// ServoParam
Servo outServ[NBOFSERVO];
int servPos[NBOFSERVO];


// Loop TimeStamp variables
unsigned long startLpTS, endLpTS, loopTime;
int i;

// Blink LED variables
int ledState[15] = {
  LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW};  //TODO : Clean this dirty memory usage
unsigned long previousTS[15] = {
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};                //TODO : Clean this dirty memory usage

// Blink LED function
void BLINK_LED(const int bLed,int bTimeUp,int bTimeDo)
{
  unsigned long currentTS = millis();
  int nowDelay;
  if (ledState[bLed]==HIGH) nowDelay=bTimeUp;
  else nowDelay=bTimeDo;
  if(currentTS - previousTS[bLed] > nowDelay) {
    previousTS[bLed] = currentTS;   
    if (ledState[bLed] == LOW) ledState[bLed] = HIGH;
    else       ledState[bLed] = LOW;
    digitalWrite(bLed, ledState[bLed]);
  }
}

// ReadReciever variables
boolean failsafe;
boolean endTrame;
unsigned long vchUp[NBOFCH+1];
int preCh; //TODO : Make this varaible cleared when entering in main loop (just use in setup)

unsigned long vchOld;

unsigned long vchLenght;

struct channel {
  int pos; // Why don't we just use an int ?
  int nxtCh;
  boolean autoP;
  int fPos;
};

struct channel ch[NBOFCH];

void DO_CHA()  // Interrupt use only to detect channel order
{
  if (PCintPort::arduinoPin==2){
    preCh=0;
    i=0;
  }
  else {
    ch[preCh].nxtCh = PCintPort::arduinoPin-2;
    preCh=PCintPort::arduinoPin-2;
    i++;
    if (i==NBOFCH-1) {
      ch[PCintPort::arduinoPin-2].nxtCh=NBOFCH;
      endTrame=1;
      preCh=PCintPort::arduinoPin-2;
    }
  }
}  

void setup()
{
  // DEBUG serial OUTPUT
  Serial.begin(57600);
  Serial.println(";");
  Serial.print("Receiver with ");
  Serial.print(NBOFCH);
  Serial.print(" channels and ");
  Serial.print(NBOFSERVO);
  Serial.println(" servos");

  Serial.print("Channel order : ");

  pinMode(LEDPINO, OUTPUT);
  pinMode(LEDPINR, OUTPUT);

  for (i=0; i < NBOFCH; i++){
    PCintPort::attachInterrupt(i+2, DO_CHA,RISING);
  }

  while(!endTrame){
    BLINK_LED(LEDPINO,50,50);
    BLINK_LED(LEDPINR,200,50);
  }

  for (i=0; i < NBOFCH; i++){
    PCintPort::detachInterrupt(i+2);
  }

  endTrame=0;

  for (int i=0; i < NBOFCH;i++) {
    Serial.print(ch[i].nxtCh);
    Serial.print(";");
  }
  Serial.println(";");

  // FailSafe Servos position
  ch[0].fPos = 1000;
  ch[1].fPos = 1500;
  ch[2].fPos = 1500;
  ch[3].fPos = 1500;

  FAILSAFE(); //Enabling FailSafe for a safe start



  // Enable final Interruption on channel's PIN
  for (int i=0; i < NBOFCH; i++){
    PCintPort::attachInterrupt(i+2, TS_REDG,RISING);
  }
  PCintPort::detachInterrupt(preCh+2);    // Detach last channel normal interrupt
  PCintPort::attachInterrupt(preCh+2, TS_CEDG,CHANGE); // Attach last channel special interrupt

  // Servo attachement
  for (int i=0; i < NBOFSERVO; i++){
    outServ[i].attach(i+NBOFCH+2);
  }

  Serial.print("SREG :");
  Serial.print(SREG,BIN);
  Serial.println(";");
  Serial.print("PCICR :");
  Serial.print(PCICR,BIN);
  Serial.println(";");
  Serial.print("PCMSK2 :");
  Serial.print(PCMSK2,BIN);
  Serial.println(";");
  Serial.print("PCMSK1 :");
  Serial.print(PCMSK1,BIN);
  Serial.println(";");
  Serial.print("PCMSK0 :");
  Serial.print(PCMSK0,BIN);
  Serial.println(";");

}




void loop()
{
  //TimeStamp Loop begining
  startLpTS = millis();

  if ((startLpTS*1000)>(vchUp[FSCH-1]+100000)){
    FAILSAFE();
  } //Detect failsafe on the (FSCH) Channel
  else{
    if (failsafe) {     //failsafe Exit  
      failsafe=0;
      digitalWrite(LEDPINR, LOW);
      endTrame=0;
    }
    else{
      if  (endTrame) { //End of trame detection
        noInterrupts(); //Stop IRQ & copy channels values
        for (int i=0; i < NBOFCH; i++){
          ch[i].pos=vchUp[ch[i].nxtCh]-vchUp[i];
        }
        vchLenght=vchUp[0]-vchOld;
        vchOld=vchUp[0];
        interrupts();  //Restart IRQ & Reset endTrameflag
        endTrame=0;
        // Set servos as Channel
        Serial.print("UPD");
        for (int i=0; i < NBOFSERVO; i++){
          outServ[i].writeMicroseconds(ch[i].pos);
        }
      }
    }
  }

  // DEBUG : Serial output the channels
  for (int i=0; i < NBOFCH; i++){
    Serial.print(ch[i].pos);
    Serial.print(";");
  }

  //Blink "normaly" the Orange LED
  BLINK_LED(LEDPINO,500,500);



  // DEBUG : Serial output the Loop Duration (ms)
  Serial.print(vchLenght); 
  Serial.print(";");
  Serial.print(micros()-vchUp[0]); 
  Serial.print(";");

  //EndLoop TimeStamp
  endLpTS = millis();
  loopTime = endLpTS - startLpTS;

  Serial.print(loopTime); 
  Serial.println(";");
}

void FAILSAFE()  // In case of lost signal
{
  Serial.print("FailSafe;");
  if (!failsafe) {
    digitalWrite(LEDPINR, HIGH);
    // Set channels on failsafe positions
    for (int i=0; i < NBOFCH; i++){
      ch[i].pos=0;
    }
    // Set servos on failsafe positions
    for (int i=1; i < NBOFSERVO; i++){
      outServ[i].writeMicroseconds(ch[i].fPos);

    }
    failsafe=1;
  }
}  


void TS_REDG()  // Same Interrupt code on all channels except the last one
{
  vchUp[PCintPort::arduinoPin-2] = micros();
}  


void TS_CEDG()  // Special interrupt on last channel
{

  // If this is a rising edge, record it
  if(PCintPort::pinState == HIGH)
  { 
    vchUp[PCintPort::arduinoPin-2] = micros();
  }
  else
  {
    //If this is a falling edge, record it as last value
    vchUp[NBOFCH] = micros();
    endTrame=1; // End of trame is set when the last falling edge of the last channel has gone !
  }
}
Last edited by unisev; Jul 15, 2012 at 04:37 PM.