token-vesting icon indicating copy to clipboard operation
token-vesting copied to clipboard

Servo & Intterupt are not working together

Open Benjamin410 opened this issue 1 year ago • 2 comments

I wanted to read via a Intterupt a multiplexed signal from an RC-Receiver (Robbe) and take the value and set it to a servo connected.

Both pices working great if they are not used together. As soon I am enable the Intterupt I am not able to set a new value to the Servo.

Every 20ms their are two interrupts which are 1 to 2ms apart, maybe the high rate is a problem.

I am using a Attiny414.

Here is the code if it helps.

#include <Servo_megaTinyCore.h>

Servo myservo;

// Variablen die in Interrupt Verwendet werden mit "volatile"
volatile int value[8] = {0};
volatile int x = 0;
volatile long nMicros = 0;
volatile long nDifference = 0;
volatile long lastChange = 0;

int oldValue = 0;

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(6, OUTPUT);
  Serial.begin(38400);
  Serial.println("Start");

  myservo.attach(0);
  myservo.writeMicroseconds(1500);
  pinMode(9, INPUT_PULLUP); // Setze Pin 9 für PPM-Eingang
  attachInterrupt(9, ppmInterrupt, CHANGE); //Starte Interrupt-Funktion wenn auf Interrupt 0(0 = Pin 3) sich das Signal ändert

  //Setzte Delay bis erste Werte in Variable value durch Interrupt geschrieben sind.
  delay(1000);
}

// the loop function runs over and over again forever
void loop() {

  if ((oldValue >=  value[0]+5) || (oldValue <=  value[0]-5)){
    
    Serial.print("M: ");
    Serial.println(value[0], DEC);
    myservo.writeMicroseconds(value[0]);
  }
  oldValue = value[0];

}
/*
ppmInterrupt
Wird Ausgeführt wenn die Flanke von Pin 9 fällt oder steigt
Wenn die 
*/
void ppmInterrupt() {
  nMicros = micros(); //Speichere aktuelle Zeit
  nDifference = (nMicros - lastChange); //Errechne Zeit seit der letzten Flanke
  if((nDifference > 700) && (nDifference < 2200)) { //HIGH Impuls herausfiltern | Wenn Zeit zwischen 700 und 2200 handelt es sich um einen HIGH Impuls
    if((nDifference > 850) && (nDifference < 995)) { //Startimpuls von 915 herausfiltern
      x = 0; //Index x auf 0 setzen damit nächste Impulse ab value[0] geschrieben werden.
      } else {
        if (x >= 8) { // Sicherheit falls Variable x zu groß wird
          x = 0;
          }
        value[x] = nDifference;// Schreibe Zeit auf Array
        x++; //Erhöhe Index um 1 für den nächsten Impuls
        }
    }
  lastChange = nMicros;// Speichere aktuelle Zeit für den nächsten Interrupt
  }

Benjamin410 avatar May 05 '24 15:05 Benjamin410

Unsure why yours does not work. I did almost exactly the same a while ago when I built a PPM to PWM converter based on a Attiny404 for a Teacher/Student buddybox. It took two PPM receivers and the teacher can define who controls the servo output. For simplicity I removed the dual input features for you, so you can give this a try.

It now takes your PPM receiver and outputs 6 servo's. If you want all 8 servo's just add two more.

#define RC_CHANS            8
volatile uint16_t rcValue_A[RC_CHANS] = {1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500}; // interval [1000;2000]

#include <Servo_megaTinyCore.h>
#define PPM_IN                  2
#define SERVO1_PIN              4
#define SERVO2_PIN              5
#define SERVO3_PIN              6
#define SERVO4_PIN              7
#define SERVO5_PIN              8
#define SERVO6_PIN              9

enum {AILERON = 0, ELEVATOR, THROTTLE, RUDDER, AUX1, AUX2, SERVO_NB}; /* enumeration to declare the index of the servos AND the amount of servos */
Servo ServoMotor[SERVO_NB]; /* Table Creation for SERVO_NB objects */

void setup() {
  ServoMotor[AILERON].attach(SERVO1_PIN);
  ServoMotor[ELEVATOR].attach(SERVO2_PIN);
  ServoMotor[THROTTLE].attach(SERVO3_PIN);
  ServoMotor[RUDDER].attach(SERVO4_PIN);
  ServoMotor[AUX1].attach(SERVO5_PIN);
  ServoMotor[AUX2].attach(SERVO6_PIN);
  attachInterrupt(PPM_IN, rxInt_A, RISING);
}

void loop() {
  ServoMotor[AILERON].writeMicroseconds(rcValue_A[0]);
  ServoMotor[ELEVATOR].writeMicroseconds(rcValue_A[1]);
  ServoMotor[THROTTLE].writeMicroseconds(rcValue_A[2]);
  ServoMotor[RUDDER].writeMicroseconds(rcValue_A[3]);
  ServoMotor[AUX1].writeMicroseconds(rcValue_A[4]);
  ServoMotor[AUX2].writeMicroseconds(rcValue_A[5]);
}

/**************************************************************************************/
/***************                PPM SUM RX Pins reading            ********************/
/**************************************************************************************/
void rxInt_A(void) {
  uint16_t now_A, diff_A;
  static uint16_t last_A = 0;
  static uint8_t chan_A = 0;
  now_A = micros();
  diff_A = now_A - last_A;
  last_A = now_A;
  if (diff_A > 3000) chan_A = 0;
  else {
    if (900 < diff_A && diff_A < 2200 && chan_A < RC_CHANS ) { //Only if the signal is between these values it is valid, otherwise the failsafe counter should move up
      rcValue_A[chan_A] = diff_A;
    }
    chan_A++;
  }
}

hmeijdam avatar May 05 '24 17:05 hmeijdam

Yes it looks very close I will test your code tomorrow if that one is working on my Attiny to see if the diffrent code or hardware could be the cause.

Benjamin410 avatar May 06 '24 11:05 Benjamin410

Your Code is working I still need to compare what the real difference is. Thank you!!!

Benjamin410 avatar May 07 '24 06:05 Benjamin410