Arduino ppm encoder

Записки программиста

Памятка по декодированию PWM и PPM сигнала

Типичная радиоаппаратура работает как-то так. Есть передатчик (собственно, сама аппа) и приемник. Приемник с передатчиком общаются по какому-то своему протоколу, часто закрытому. Приемник декодирует этот протокол и передает положение ручек на аппаратуре дальше, например, полетному контроллеру (ПК) квадрокоптера. ПК и приемник общаются по своему протоколу, который должны понимать оба. В этом месте большой популярностью пользуются PWM и PPM. Есть и другие варианты, в частности, SBUS, DSM2 и DSX, но в рамках данной статьи мы рассмотрим только PWM и PPM.

PWM (Pulse Width Modulation), он же ШИМ, всем хорошо знаком. Раз в 20 мс по проводу передается положительный импульс, длительность которого определяет положение ручки. Длительность импульса около 1000 микросекунд соответствует одному крайнему положению, а 2000 микросекунд — другому крайнему положению. На практике присутствует некоторая ошибка измерения, из-за чего, в частности, полетный контроллер и аппаратура требуют калибровки. PWM прост и понятен, но плох тем, что требует отдельного провода на каждый канал (то есть, каждую ручку аппаратуры). Сейчас многие аппаратуры имеют 8 и более каналов, а значит при использовании PWM приходится использовать много проводов.

PPM (Pulse Position Modulation) — это такая попытка запихнуть много PWM сигналов в один провод, ну или, по крайней мере, мне лично нравится о нем так думать. PPM всегда передает короткие импульсы. Паузы между фронтами импульсов соответствуют длительности одного PWM сигнала. Сигналы передаются последовательно, сначала значение на первом канале, затем на втором, и так далее. Соответствие между PPM и PWM сигналами хорошо отражает следующая осциллограмма, записанная на Rigol DS1054Z:

Осциллограмма снята с приемника RadioLink R8EF, имеющего режим, при котором на два его пина подаются сигналы PPM и SBUS, а на остальные пины — PWM сигнал для каналов с 3 по 8. Поэтому PWM сигналы для каналов 1 и 2 не показаны. Тут можно видеть несколько интересных особенностей. Во-первых, данный конкретный приемник использует для логической единицы 3.3 В, хотя и питается от 5 В. Во-вторых, в нем PPM сигнал инвертирован по сравнению с тем, как его обычно рисуют на картинках (например, в этом треде). Как ни странно, все написанное выше про фронты импульсов при этом остается верным. В частности, на картинке курсорами выделены фронты, соответствующие PWM сигналу на 3 канале. При этом PPM сигнал оказывается смещенным относительно PWM сигналов, но вообще-то приемник и не обязан был их как-то синхронизировать.

PPM работает хорошо до тех пор, пока вы не пытаетесь засунуть в него больше 8 каналов. Если каналов больше, то либо сигналы начинают обновляться с задержкой больше 20 мс (как в случае с PWM), либо приходится «сжимать» сигналы, теряя их точность, либо использовать дополнительные провода. Лично я не видел, чтобы по PPM передавали больше 8 каналов.

Хорошо, теперь допустим, что я хочу управлять своим роботом при помощи радиоаппаратуры. Вот соответствующий код для PWM:

#define NCHANNELS 8
#define CH1_PIN 5 // CH2_PIN = CH1_PIN + 1, etc

volatile int pwm_value [ NCHANNELS ] = < 0 >;
volatile int prev_time [ NCHANNELS ] = < 0 >;

void falling ( ) <
uint8_t pin = PCintPort :: arduinoPin ;
PCintPort :: attachInterrupt ( pin, & rising, RISING ) ;
pwm_value [ pin — CH1_PIN ] = micros ( ) — prev_time [ pin — CH1_PIN ] ;
>

void rising ( )
<
uint8_t pin = PCintPort :: arduinoPin ;
PCintPort :: attachInterrupt ( pin, & falling, FALLING ) ;
prev_time [ pin — CH1_PIN ] = micros ( ) ;
>

void setup ( ) <
for ( uint8_t i = 0 ; i NCHANNELS ; i ++ ) <
pinMode ( CH1_PIN + i, INPUT_PULLUP ) ;
PCintPort :: attachInterrupt ( CH1_PIN + i, & rising, RISING ) ;
>

Serial. begin ( 9600 ) ;
>

void loop ( ) <
for ( uint8_t i = 0 ; i NCHANNELS ; i ++ )
Serial. println ( «ch» + String ( i + 1 ) + » = » + String ( pwm_value [ i ] ) ) ;
Serial. println ( «—————-» ) ;
delay ( 1000 ) ;
>

А это — код для PPM:

#define PPM_PIN 6
#define MAX_CHANNELS 12

volatile int pwm_value [ MAX_CHANNELS ] = < 0 >;
volatile int prev_time = 0 ;
volatile int curr_channel = 0 ;

volatile bool overflow = false ;

void rising ( )
<
int tstamp = micros ( ) ;

/* overflow should never acutally happen, but who knows. */
if ( curr_channel MAX_CHANNELS ) <
pwm_value [ curr_channel ] = tstamp — prev_time ;
if ( pwm_value [ curr_channel ] > 2100 ) < /* it's actually a sync */
pwm_value [ curr_channel ] = 0 ;
curr_channel = 0 ;
> else
curr_channel ++ ;
> else
overflow = true ;

void setup ( ) <
pinMode ( PPM_PIN, INPUT_PULLUP ) ;
PCintPort :: attachInterrupt ( PPM_PIN, & rising, RISING ) ;

Serial. begin ( 9600 ) ;
>

void loop ( ) <
for ( uint8_t i = 0 ; i MAX_CHANNELS ; i ++ )
Serial. println ( «ch» + String ( i + 1 ) + » = » + String ( pwm_value [ i ] ) ) ;
if ( overflow )
Serial. println ( «OVERFLOW!» ) ;
Serial. println ( «—————-» ) ;
delay ( 1000 ) ;
>

Код был проверен на радиоаппаратуре RadioLink T8FB и приемнике к ней R8EF. На следующем фото приемник, переведенный в режим PPM, подключен к Arduino Nano с залитой в нее прошивкой для PPM:

Пример отладочного вывода по UART:

Назначение использованной выше библиотеки PinChangeInt должно быть понятно по коду. Она позволяет вешать прерывания на передний и задний фронты (нарастание и спад) сигнала на заданных пинах. Подробности об этой библиотеке можно найти здесь и здесь. Полная версия кода прошивок для декодирования PWM и PPM сигналов доступна на GitHub.

Вооруженные полученными здесь знаниями, мы можем не только управлять Arduino при помощи радиоаппаратуры, но и, например, паять перекодировщики PWM в/из PPM (если не хочется платить за готовые на AliExpress), или даже изготавливать собственные радиоаппаратуры на базе какого-нибудь NRF24L01 или иного радиомодуля. Это просто первое что мне лично пришло в голову.

А какие безумные идеи для творчества есть у вас?

Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.

Источник

DIY PWM to PPM Converter for 2.4GHz Receiver using Arduino

For radio receiver, there are a few output signal formats. The traditional and also most common type of RX signal is the PWM and basically PWM requires 1 cable per channel. PPM is now getting more and more popular, because it can handle all 8 channels in 1 signal wire.

You can buy a commercially ready PWM to PPM converter (which also does SBUS output as well): Amazon | Banggood | GetFPV

But for those who enjoy tinkering and DIY, here is a fun project for you.

Al Prettybong on Multicopter International Group shared with me how he made a PWM to PPM converter using an Arduino Pro Mini, and I thought I should share this with everyone.

Buy the Arduino from: Banggood | Amazon

Connection

The connection is really simple.

5V and GND on receiver is connected to “RAW” and GND pins on the Arduino board. Ch1 to Ch8 is connected D0 to D7 on the Arduino. (if you are using receiver that has fewer channels, you don’t have to worry about the rest of the pins on the Arduino)

For a more detail connection diagram, check out the top picture in this article.

He removed all the servo pins on this receiver, and soldered direct the arduino pwm to ppm converter. He said this has been running successfully for about 8 months, and i did the same conversion on an 8 channel receiver also has failsafe built in to the pwm ppm converter. Failsafe channel can be set up in the code.

There are 3 wires that will be connected to the FC, 5V, GND and PPM (Green).

And finally he put heatshrink over this unit, and now this cheap PWM RX has turned into a powerful PPM RX :) He put clear heatshrink in the middle so he could see the status LEDs.

Upload Sketch on Arduino

I haven’t tested this code yet, but Al told me there is NO changes to the code, just copy and upload it to your Arduino and it will work.

Here is the main sketch.

And then create a new tab in your Arduino IDE and copy this, name it “ppm_encoder.h”, and copy the following code in the tab.

tBeacon – Lost Model/Plane/Multicopter GPS Tracker
Mount Camera Gimbal on Mini Quadcopter – Feiyu Mini3D 3-Axis Review

Leave a Comment Cancel Reply

30 comments

Just wanted to say Hrvoje’s solution above worked first try. My servo breakout board has a couple different pins, but after two minutes of swapping attempts, all good. The “S2PW” converter board I bought on ebay was super jittery with the PPM conversion, but this Arduino Nano is smooth as silk.

Grateful a lot for the work done!
Everything works great and I was able to connect the FS-i6 + iA6 to my computer for Liftoff training without any problems! I wish you success and good luck in everything!

Compilation error in line
// ———————————————— ——————————
ISR (SERVO_INT_VECTOR)
<
file ppm_encoder.h

Hi Oscar. It does not work for me.. I was using arduino micro though, but anyway it should make no difference. There is much better (and simpler) solution which i have tried and it works great on my flysky receiver using arduino nano (ATmega328p chip) so i will describe the process maybe it will help someone.

1. download .hex file from this location:
ardupilot.org/plane/docs/common-downloads_advanced_user_tools.html#arduppm-v2-3-16-atmega328p-firmware-for-apm1-x-copter-and-standalone-ppm-encoder

You should download:
ArduPPM_v2.3.16_ATMega328p_for_ArduCopter.hex_.zip for copter or
ArduPPM_v2.3.16_ATMega328p_for_ArduPlane.hex_.zip for plane.

2. Download Xloader:
You can download Xloader from here: xloader.russemotto.com/
Unzip the file.

3. Connect Arduino and receiver assembly (wiring as described by Oscar’s blog, see picture on top of this page for wiring) to computer via USB

4. Run Xloader.exe and fill in:
.hex file location (browse to wherever it is saved on your computer)
Chose device from the list (in my case it is Nano ATmega328)
Chose COM port where you plugged in your arduino to computer USB (in my case COM6)
Baud rate should automatically change so you dont have to change it (in my case is 57600)

PRESS UPLOAD and you are done!

The .hex file will download straight to your arduino board and now you have PPM encoder.

Have fun, happy flying!

I converted my Turnigy9x from PWM to PPM successfully:
photos.app.goo.gl/veqGmXUtn2a3t0zr1

Make connections as shown in the picture. I used the ArduPPM encoder firmware which is actually for their PPM encoder (ardupilot.org/copter/docs/common-ppm-encoder-8-channel-standalone-encoder.html) but works well for the Arduino Pro Mini as well.

Download the .hex file for their firmware (ArduPPM for ArduCopter), and flash it using an USBasp programmer and programming software (like SinaProg). Connections are made for programming as shown here: samopal.pro/wp13_samopal/wp-content/uploads/561/cxema.jpg

You can contact me at srijal97_at_gmail.com for any clarifications.

I have a new 6ch transmitter branded FS-CT6B from Flysky and 6ch FS-R6B receiver with only PWM output, the question is can your arduino 8ch program for 6ch receiver ?, or should I reduce the program line to fit my 6ch receiver ? , or your arduino program can already work on receivers under 8ch ?

Hi Oscar, can I use ppm encoder for racing quad?

Источник

goTechTown/PPM_Decoder

Use Git or checkout with SVN using the web URL.

Work fast with our official CLI. Learn more.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching Xcode

If nothing happens, download Xcode and try again.

Launching Visual Studio Code

Your codespace will open once ready.

There was a problem preparing your codespace, please try again.

Latest commit

Git stats

Files

Failed to load latest commit information.

README.md

A class for decoding a Pulse Position Modulation signal used by many remote controllers. This class is primarily for use with Arduinos.

PPM_Decoder( pinNbr , nbrOfChs, nbrOfSams, syncTimeMs )

Creates a PPM_Decoder object (constructor).

  • uint8_t pinNbr: the pin where the PPM signal in coming in.
  • unsigned nbrOfChs: the number of channels being transmitted.
  • unsigned nbrOfSams: The number of samples to take and average. Default is 1.
  • unsigned long syncTimeMs: The sync time of the PPM signal in milliseconds. Default is 5000.

Returns whether or not the decoder object is valid. The object allocates memory internally and if the allocation fails, the object will be invalid.

true — object is valid
false — object is not valid.

##void update() Updates the channel values received. If ­nbrOfSams (in the constructor) is > 1, then multiples values are received.

unsigned value( channel )

Returns the value of the requested channel. If ­nbrOfSams (in the constructor) is > 1, then the average value is returned.

About

An Arduino library to decode RF PPM signals.

Источник

speters/pwm2x

Use Git or checkout with SVN using the web URL.

Work fast with our official CLI. Learn more.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching Xcode

If nothing happens, download Xcode and try again.

Launching Visual Studio Code

Your codespace will open once ready.

There was a problem preparing your codespace, please try again.

This branch is 9 commits ahead of davidbuzz:master.

Open a pull request to contribute your changes upstream.

Latest commit

Git stats

Files

Failed to load latest commit information.

README.md

#PWM to PPM & SBUS converter

originated from buzz’s 8 channel PWM to PPM converter for RC use

  • an Arduino with a Atmega328 or 328p chip on it.
  • IDE to program the chip with this code.

Used Arduino IDE to program this firmware onto the Arduino chip.

Connect upto 8 RC PWM input signals so that the wires go to: red = 5v black = GND or 0V pin on arduino white = PWM signal pins, these connect to D8,D9,D2,D3,D4,D5,D6,D7

Connect the PPM output so that the wires go to: red = 5v black = GND or 0V PPM out = D10

  • any channel that you don’t connect a PWM input on, will emit a default value ( which is 1500 for all channels excpt throttle, which is 1100.
  • disconnecting any channel after booting will cause the system to use the last-known-position of the input, until a good signal returns.
  • having pin PC3 (Arduino A3) pulled high on startup produces human readable serial 115200,8n1 output of the channel data instead of sbus
  • This is not a «failsafe» unit, if has no failsafe functionality.
  • If this code causes your expensive toys to crash, or worse, it’s your fault for being a bad person, so you should be nicer, as karma’s a bitch.
  • Not my fault. none of it. I love you too, now go away.

About

PWM to SBUS and PPM converter (pwm2ppm, pwm2sbus) for Arduino AVR atmega328p

Источник

Adblock
detector