bare-bones PPM signal generation

I know, there are multiple posts about this, but I am looking for the bare-bone version of the PPM Signal Generation.

Basically, Serial.read the value from the Serial Monitor and converting that into one channel of the PPM signal.

//this programm will put out a PPM signal

//////////////////////CONFIGURATION///////////////////////////////
#define chanel_number 8  //set the number of chanels
#define default_servo_value 1500  //set the default servo value
#define PPM_FrLen 22500  //set the PPM frame length in microseconds (1ms = 1000µs)
#define PPM_PulseLen 300  //set the pulse length
#define onState 0  //set polarity of the pulses: 1 is positive, 0 is negative
#define sigPin 10  //set PPM signal output pin on the arduino
//////////////////////////////////////////////////////////////////


/*this array holds the servo values for the ppm signal
  change theese values in your code (usually servo values move between 1000 and 2000)*/
int ppm[chanel_number];

String readString;

void setup() {
  Serial.begin(9600);

  //initiallize default ppm values
  for (int i = 0; i < chanel_number; i++) {
    ppm[i] = default_servo_value;
  }

  pinMode(sigPin, OUTPUT);
  digitalWrite(sigPin, !onState);  //set the PPM signal pin to the default state (off)

  cli();
  TCCR1A = 0; // set entire TCCR1 register to 0
  TCCR1B = 0;

  OCR1A = 100;  // compare match register, change this
  TCCR1B |= (1 << WGM12);  // turn on CTC mode
  TCCR1B |= (1 << CS11);  // 8 prescaler: 0,5 microseconds at 16mhz
  TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
  sei();
}

void loop() {

  if (Serial.available())  {
    char c = Serial.read(); 
    if (c == ',') {
      if (readString.length() > 1) {

        Serial.print("recieving data\n");
        int intValue = readString.toInt();

        if ((intValue >= 1000) && (intValue <= 2000) && (readString.indexOf("i") > 0)) {
          ppm[0] = intValue;
          Serial.println("value: ");
          Serial.println(ppm[0]);
        }
  
      }
      readString = "";
    }
    else {
      readString += c;
    }
  }
  Serial.flush();

  //put main code here
  static int val = 1;

  ppm[0] = ppm[0] + val;
  if (ppm[0] >= 2000) {
    val = -1;
  }
  if (ppm[0] <= 1000) {
    val = 1;
  }
  delay(10);
}

ISR(TIMER1_COMPA_vect) { //leave this alone
  static boolean state = true;

  TCNT1 = 0;

  if (state) { //start pulse
    digitalWrite(sigPin, onState);
    OCR1A = PPM_PulseLen * 2;
    state = false;
  }
  else { //end pulse and calculate when to start the next pulse
    static byte cur_chan_numb;
    static unsigned int calc_rest;

    digitalWrite(sigPin, !onState);
    state = true;

    if (cur_chan_numb >= chanel_number) {
      cur_chan_numb = 0;
      calc_rest = calc_rest + PPM_PulseLen;//
      OCR1A = (PPM_FrLen - calc_rest) * 2;
      calc_rest = 0;
    }
    else {
      OCR1A = (ppm[cur_chan_numb] - PPM_PulseLen) * 2;
      calc_rest = calc_rest + ppm[cur_chan_numb];
      cur_chan_numb++;
    }
  }
}

One channel of PPM?
What are you trying to do?

I just need to control one signal. Even though it might not be the easiest option, I have to go via PPM.

Thank you

OK, I'll try again.

What are you trying to do?

Have you tried setting "chanel_number" to one?

(I'm not sure one channel of PPM makes any sense, but I'm hoping you'll enlighten me, when you've finished reading my profile)

I have a Spektrum receiver which is 8 channels, and I want to generate the PPM signal via Arduino and send it via trainer port.
For the test setup I only have one Servo on the other end. If it works with one, I can later update the ppm array for the other channels.

(I hope I enlightened you) :wink:

I have absolutely no idea what a “Spektrum receiver”, but it sounds to me like you need the output of one instance of the Servo class.

Because it is a single channel, it is not (cannot be) PPM (position relative to what?), but is in fact, PWM.

it’s just a standard RC receiver that wants ppm input.
ok, let’s say I want to set all 8 channels to a different value.
I will index every channel with a different letter and assign the value to the array accordingly.

My ppm receiver doesn’t react to the input of my code at all.
When I use a pwm to ppm converter it works just fine.

I thought it must be possible to send the PPM right out of the Arduino instead of using the external board to convert the Arduino PWM to PPM.

if ((intValue >= 1000) && (intValue <= 2000) && (readString.indexOf("a") > 0)) {
          ppm[0] = intValue;
          Serial.println("value: ");
          Serial.println(ppm[0]);
        }

 if ((intValue >= 1000) && (intValue <= 2000) && (readString.indexOf("b") > 0)) {
          ppm[0] = intValue;
          Serial.println("value: ");
          Serial.println(ppm[1]);
        }

 if ((intValue >= 1000) && (intValue <= 2000) && (readString.indexOf(c") > 0)) {
          ppm[0] = intValue;
          Serial.println("value: ");
          Serial.println(ppm[2]);
        }

...

I'm guessing that the OP wants to create (say) 6 servo signals and combine them into a single stream as is done by an R/C transmitter.

This needs to be confirmed by the OP.

If that is what is needed I can conceive of an Arduino program that could do that. It would need to generate a succession of HIGH pulses each with a width appropriate to the setting for the relevant servo - perhaps drawing from an array containing the different widths in microseconds.

It should not be too difficult. Have a look at how timing is done in Several Things at a Time - but think of micros() rather than millis().

...R

thank you for all your input!.

I want to generate a standard 8-Channel PPM Signal, although I don't need to access all 8 Channels. If I can send data on 2 I am more than happy. However since the receiver expects a 8 Channel PPM input I have to send 8 Channels, the ones that are not used can be 'empty' or centered.

If you just send a single PWM stream into an R/C receiver, I would expect it to control only the first output channel, because the counter in the receiver would be reset very shortly after each pulse was received.
You need all the pulses in the frame, even if some are dummies.

objectr:
I want to generate a standard 8-Channel PPM Signal,

I believe that is what I described in the 3rd paragraph of Reply #7

...R