SpenceKonde / megaTinyCore

Arduino core for the tinyAVR 0/1/2-series - Ones's digit 2,4,5,7 (pincount, 8,14,20,24), tens digit 0, 1, or 2 (featureset), preceded by flash in kb. Library maintainers: porting help available!
Other
542 stars 140 forks source link

Servo & Intterupt are not working together #1096

Closed Benjamin410 closed 1 month ago

Benjamin410 commented 2 months ago

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
  }
hmeijdam commented 2 months ago

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++;
  }
}
Benjamin410 commented 1 month ago

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 commented 1 month ago

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