Go Down

Topic: Arduino due / ppm (Read 5093 times) previous topic - next topic

Sijjim

Ok, you really wants the same code back? Please test it, i dont have an Due now. But hope this problem isnt one, when i have my own.
Get the Lib from ivanseidel/DueTimer
and test this:

Code: [Select]
#include <DueTimer.h>

#define chanel_number 8
#define default_servo_value 1500
#define PPM_FrLen 22500
#define PPM_PulseLen 300
#define sigPin 10
#define onState 1

int ppm[chanel_number];

void doit(){
  static boolean state = true;
  if(state){
    digitalWrite(sigPin, onState);
    Timer3.attachInterrupt(doit).setPeriod(PPM_PulseLen);
    state = false;
  } else {
    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;
      Timer3.attachInterrupt(doit).setPeriod(PPM_FrLen - calc_rest);
      calc_rest = 0;
    } else {
      Timer3.attachInterrupt(doit).setPeriod(ppm[cur_chan_numb] - PPM_PulseLen);
      calc_rest = calc_rest + ppm[cur_chan_numb];
      cur_chan_numb++;
    }
  }     
}

void setup(){
  for (int i = 0; i < chanel_number; i++){
    ppm[i] = default_servo_value;
  }
  pinMode(sigPin, OUTPUT);
  digitalWrite(sigPin, !onState);
  Timer3.attachInterrupt(doit).start(1000);
}

void loop(){
  while(1){ }
}

Francois

#16
Dec 12, 2013, 02:57 am Last Edit: Dec 12, 2013, 03:03 am by Francois Reason: 1
Thank you very much for your help, I will be able to check the code on Friday (I do not have an osciloscope at home  =( ).

Here is what i would like to learn to do on the arduino due ( in green is the equivalent code for the arduino uno):

1. Setup a timer on the due & Start a timer  
  cli();
 TCCR1A = 0;                        // set entire TCCR1 register to 0
 TCCR1B = 0;
 OCR1A = 100;                     // compare match register
 TCCR1B |= (1 << WGM12);   // turn on CTC mode
 TIMSK1 |= (1 << OCIE1A);    // enable timer compare interrupt
 sei();


2. Set a presacaler
  TCCR1B |= (1 << CS11);    // 8 prescaler: 0,5 microseconds at 16mhz

3. Change the match register (trigger)
  OCR1A = XXX // what every value i decide

4. Run into a loop every time the match register is reached
  ISR(TIMER1_COMPA_vect){ code }

Is it possible to do ?

Sijjim

#17
Dec 12, 2013, 10:01 am Last Edit: Dec 12, 2013, 10:03 am by Sijjim Reason: 1
First, if u have an other Arduino, i use this sketch on a Uno for fast bugfixing:

Code: [Select]
#define channumber 7 //How many channels have your radio?
int value[channumber];

void setup()
{
Serial.begin(57600); //Serial Begin
pinMode(3, INPUT); //Pin 3 as input
}
void loop()
{
while(pulseIn(3, LOW) < 5000){} //Wait for the beginning of the frame
// while(pulseIn(3, HIGH) < 5000){} //alt for invert signal
for(int x=0; x<=channumber-1; x++)//Loop to store all the channel position
{
value[x]=pulseIn(3, LOW);
// value[x]=pulseIn(3, HIGH); //alt for invert signal
}
for(int x=0; x<=channumber-1; x++)//Loop to print and clear all the channel readings
{
Serial.print(value[x]); //Print the value
Serial.print(" ");
value[x]=0; //Clear the value afeter is printed
}
Serial.println(""); //Start a new line
}

Just hang pin 3 from this one to ppm-out on Due an connect ground together.

and the other points, look to stimmers code too:

Quote
1. Setup a timer on the due & Start a timer  

Code: [Select]
REG_PIOB_PDR = 1<<25; // disable PIO, enable peripheral
 REG_PIOB_ABSR= 1<<25; // select peripheral B
 REG_TC0_WPMR=0x54494D00; // enable write to registers
//REG_TC0_CMR0=0b00000000000010011100010000000000; // set channel mode register (see datasheet)
 REG_TC0_CMR0=0b00000000000001101100010000000000; // alternative CMR for inverted output
 REG_TC0_RC0=100000000; // counter period
 REG_TC0_CCR0=0b101;    // start counter
 REG_TC0_IER0=0b00010000; // enable interrupt on counter=rc
 REG_TC0_IDR0=0b11101111; // disable other interrupts


Quote
2. Set a presacaler

not sure, think its inside this part, the TCCLKS, look in datasheet at page 869, Table 37-1 and page 904
Code: [Select]
REG_TC0_CMR0=0b00000000000001101100010000000000;

Quote
3. Change the match register (trigger)

Code: [Select]
REG_TC0_RC0= XXX

Quote
4. Run into a loop every time the match register is reached

Code: [Select]
void TC0_Handler() { code }

greetings

VerlatyAlex

#18
Feb 25, 2015, 10:28 am Last Edit: Feb 25, 2015, 06:25 pm by VerlatyAlex
Good day.
I'm not an experienced programmer Arduino, had a lot to deal with timers Atmel SAM3X8E ARM Cortex-M3 NC.
Helped Frankois code in this post.
Thank very much for Frankois working code.
I redid it and simplified.
Code 100% working on Arduino Due.
My code changes PPM signal to the respective signals at the inputs A0-A2.

Code: [Select]

#define PPM_PIN 2             // выход PPM
#define MAX_PPM_CHANNELS 8
#define PPM_FrLen 22500
#define PPM_PulseLen 250
int ppm[MAX_PPM_CHANNELS];
int PPMmin = 900;
byte PPM_cur_ch = 0;
unsigned int PPM_sum = 0;

void setup() {
  pinMode(PPM_PIN, OUTPUT);          // port B pin 25
  analogWrite(PPM_PIN, 255);         // sets up some other registers I haven't worked out yet

  // timer is clocked at 42MHz, so 42 ticks per us
  REG_PIOB_PDR  = 1 << 25;     // disable PIO, enable peripheral
  REG_PIOB_ABSR = 1 << 25;     // select peripheral B
  REG_TC0_WPMR  = 0x54494D00;  // enable write to registers
  // REG_TC0_CMR0  = 0b00000000000010011100010000000000; // set channel mode register (see datasheet)
  REG_TC0_CMR0  = 0b00000000000001101100010000000000; // alternative CMR for inverted output
  REG_TC0_RC0   = 100000000;   // counter period
  REG_TC0_CCR0  = 0b101;       // start counter
  REG_TC0_IER0  = 0b00010000;  // enable interrupt on counter = rc
  REG_TC0_IDR0  = 0b11101111;  // disable other interrupts

  REG_TC0_RA0   = PPM_PulseLen * 42; // Pulse lenght
  NVIC_EnableIRQ(TC0_IRQn);    // enable TC0 interrupts

  for (int i = 0; i < MAX_PPM_CHANNELS; i++) ppm[i] = PPMmin;
}

void TC0_Handler()
{
  long dummy = REG_TC0_SR0;  // vital - reading this clears some flag, otherwise you get infinite interrupts
  if (PPM_cur_ch < MAX_PPM_CHANNELS)
  {
    REG_TC0_RC0 = ppm[PPM_cur_ch] * 42;
    PPM_sum += ppm[PPM_cur_ch];
    PPM_cur_ch++;
  }
  else
  {
    REG_TC0_RC0 = (PPM_FrLen - PPM_sum) * 42;
    PPM_cur_ch = 0;
    PPM_sum = 0;
  }
}

void loop()
{
  ppm[0] = PPMmin + analogRead(0);
  ppm[1] = PPMmin + analogRead(1);
  ppm[2] = PPMmin + analogRead(2);
  
  
}


Sijjim's code in this post must be changed.
Each row in the:
Timer3.attachInterrupt (doit) .setPeriod (PPM_PulseLen);
Timer3.attachInterrupt (doit) .setPeriod (PPM_FrLen - calc_rest);
Timer3.attachInterrupt (doit) .setPeriod (ppm [cur_chan_numb] - PPM_PulseLen);
it is necessary to add the start ()

Corrected row looks like this:
Timer3.attachInterrupt (doit) .setPeriod (PPM_PulseLen). start ();
Timer3.attachInterrupt (doit) .setPeriod (PPM_FrLen - calc_rest). start ();
Timer3.attachInterrupt (doit) .setPeriod (ppm [cur_chan_numb] - PPM_PulseLen). start ();

VerlatyAlex

#19
Feb 25, 2015, 10:56 am Last Edit: Feb 25, 2015, 10:59 am by VerlatyAlex
To read the PPM signal in my project using this code:
Code: [Select]
#define MAX_PPM_CHANNELS 8          // we are working with an 8-ch-Transmitter
#define PPM_PIN 3           // Input Pin Number

const int FrameSpace = 2500;
unsigned long Last_Time;
unsigned long Current_Time;
unsigned long Delta_Time;
volatile byte Current_Channel = 0;
volatile int Channel[MAX_PPM_CHANNELS];

void setup()
{
    attachInterrupt(1, CalcPPM, RISING);
    Last_Time = micros(); 
    Serial.begin(9600);
}

void CalcPPM()
{
  Current_Time = micros();
  Delta_Time = Current_Time - Last_Time;
  Last_Time = Current_Time;
  if (Delta_Time > FrameSpace) Current_Channel = 0;
  else
  {
    Channel[Current_Channel]=Delta_Time;
    Current_Channel++;
  }   


void loop()
{
  for ( byte x = 0; x < MAX_PPM_CHANNELS; x++)
  {
    Serial.print("Ch. ");
    Serial.print(x);
    Serial.print(": ");
    Serial.print(Channel[x]); 
    Serial.print("      ");
  }
  Serial.println();
 }
 
 


Checked this code to Arduino Due, Mega and Pro Mini.
This code works 100%.

To use the Due need to change the line:

attachInterrupt(1, CalcPPM, RISING);

to:

attachInterrupt(PPM_PIN, CalcPPM, RISING);

Paul Stoffregen

I recently wrote a PPM signal library called PulsePosition.


http://www.pjrc.com/teensy/td_libs_PulsePosition.html


It's designed around Teensy's timers, but if someone wanted to get a good start on a Due-based library, maybe this could at least help?

Grippentech

#21
Aug 17, 2015, 02:56 pm Last Edit: Aug 17, 2015, 03:10 pm by Grippentech
Can confirm Alex's code works great on the Due!



AWOL

Quote
so something like Serial.begin(9600); fails saying serial is not defined or something along those lines.
Instead of saying "something like" or "along the lines of" why don't you simply post the code you've got and the error message(s) you're getting?

Anything else is just time-wasting.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Go Up