Re: PPM энкодер на ...дуино
Попробуй . Если не подойдет что нибудь придумаем
Вложений: 1
Re: PPM энкодер на ...дуино
Спасибо, я реально сам не разберусь.
С мегой не заработала, пока разбирался с портами, то нашел еще вариант. Как-то больше доверия :)
Пожалуйста, если сразу видно проблемность кода, тормозните.
Я так понял из библиотеки, что можно использовать на выбор любой из 3-х таймеров? С мегой работать будет?
PHP код:
#include <PinChangeInt.h> // http://www.arduino.cc/playground/Main/PinChangeInt
#include <PinChangeIntConfig.h>
#include <TimerOne.h> // http://www.arduino.cc/playground/Code/Timer1
#define NO_PORTB_PINCHANGES //PinChangeInt setup
#define NO_PORTC_PINCHANGES //only port D pinchanges (see: http://www.arduino.cc/playground/Learning/Pins)
#define PIN_COUNT 3 //number of channels attached to the reciver
#define MAX_PIN_CHANGE_PINS PIN_COUNT
#define RC_TURN 3 //arduino pins attached to the reciver
#define RC_FWD 2
#define RC_FIRE 4
byte pin[] = {RC_FWD, RC_TURN, RC_FIRE}; //for maximum efficency thise pins should be attached
unsigned int time[] = {0,0,0}; // to the reciver's channels in the order listed here
byte state=0;
byte burp=0; // a counter to see how many times the int has executed
byte cmd=0; // a place to put our serial data
byte i=0; // global counter for tracking what pin we are on
void setup() {
Serial.begin(115200);
Serial.print("PinChangeInt ReciverReading test");
Serial.println(); //warm up the serial port
Timer1.initialize(2200); //longest pulse in PPM is usally 2.1 milliseconds,
//pick a period that gives you a little headroom.
Timer1.stop(); //stop the counter
Timer1.restart(); //set the clock to zero
for (byte i=0; i<3; i++)
{
pinMode(pin[i], INPUT); //set the pin to input
digitalWrite(pin[i], HIGH); //use the internal pullup resistor
}
PCintPort::attachInterrupt(pin[i], rise,RISING); // attach a PinChange Interrupt to our first pin
}
void loop() {
cmd=Serial.read(); //while you got some time gimme a systems report
if (cmd=='p')
{
Serial.print("time:\t");
for (byte i=0; i<PIN_COUNT;i++)
{
Serial.print(i,DEC);
Serial.print(":");
Serial.print(time[i],DEC);
Serial.print("\t");
}
Serial.print(burp, DEC);
Serial.println();
/* Serial.print("\t");
Serial.print(clockCyclesToMicroseconds(Timer1.pwmPeriod), DEC);
Serial.print("\t");
Serial.print(Timer1.clockSelectBits, BIN);
Serial.print("\t");
Serial.println(ICR1, DEC);*/
}
cmd=0;
switch (state)
{
case RISING: //we have just seen a rising edge
PCintPort::detachInterrupt(pin[i]);
PCintPort::attachInterrupt(pin[i], fall, FALLING); //attach the falling end
state=255;
break;
case FALLING: //we just saw a falling edge
PCintPort::detachInterrupt(pin[i]);
i++; //move to the next pin
i = i % PIN_COUNT; //i ranges from 0 to PIN_COUNT
PCintPort::attachInterrupt(pin[i], rise,RISING);
state=255;
break;
/*default:
//do nothing
break;*/
}
}
void rise() //on the rising edge of the currently intresting pin
{
Timer1.restart(); //set our stopwatch to 0
Timer1.start(); //and start it up
state=RISING;
// Serial.print('r');
burp++;
}
void fall() //on the falling edge of the signal
{
state=FALLING;
time[i]=readTimer1(); // read the time since timer1 was restarted
// time[i]=Timer1.read(); // The function below has been ported into the
// the latest TimerOne class, if you have the
// new Timer1 lib you can use this line instead
Timer1.stop();
// Serial.print('f');
}
unsigned long readTimer1() //returns the value of the timer in microseconds
{ //rember! phase and freq correct mode counts
//up to ICR1 then down again
unsigned int tmp=TCNT1;
char scale=0;
switch (Timer1.clockSelectBits)
{
case 1:// no prescalse
scale=0;
break;
case 2:// x8 prescale
scale=3;
break;
case 3:// x64
scale=6;
break;
case 4:// x256
scale=8;
break;
case 5:// x1024
scale=10;
break;
}
while (TCNT1==tmp) //if the timer has not ticked yet
{
//do nothing -- max delay here is ~1023 cycles
}
tmp = ( (TCNT1>tmp) ? (tmp) : (ICR1-TCNT1)+ICR1 );//if we are counting down add the top value
//to how far we have counted down
return ((tmp*1000L)/(F_CPU /1000L))<<scale;
}
Вложений: 1
Re: PPM энкодер на ...дуино
Вот мой РРМ сигнал на фото.
Период 22 мс.
Стробирующий положительный импульс 0,5 мс.
1 канал - отрицательный импульс 1,0 мс.
Стробирующий положительный импульс 0,5 мс.
2 канал - отрицательный импульс 1,0 мс.
Стробирующий положительный импульс 0,5 мс.
3 канал - отрицательный импульс 1,5 мс.
Стробирующий положительный импульс 0,5 мс.
4 канал - отрицательный импульс 1,0 мс.
Стробирующий положительный импульс 0,5 мс.
и т.д.
Вложений: 1
Re: PPM энкодер на ...дуино
А это шум при отключенном передатчике, установки осциллографа те же.
После включения передатчика и до конца инициализации на выходе появляется ноль, а потом пошли пачки сигналов.
Re: PPM энкодер на ...дуино
А может забыть про универсальные библиотеки, а начать самостоятельно писать и навыки в программировании получу и другим возможно поможет.
Длительность канального отрицательного импульса регулируется передатчиком в пределах 0,5 - 1,5 мс.
Синхроимпульсы вначале, между каналами и в конце, все по 0,5 мс.
Пауза после пачки 5,8 - 13,8 мс.
Период, как я уже писал немного более 22 мс.
После пачки сигналов, минимальная пауза 5,8 мс.
Значит ловим 5 мс. отрицательных и обнуляем счетчик каналов.
Ждем первого перехода с 1 в 0, после которого таймер отсчитывает длительность отрицательного импульса и присваивает это значение первому каналу.
Увеличиваем счетчик каналов на 1.
Все в цикле до прихода паузы длительностью более 5 мс.
Re: PPM энкодер на ...дуино
Не пойму у тебя он что цифру выдает?
Re: PPM энкодер на ...дуино
Цитата:
Сообщение от
Chip
Не пойму у тебя он что цифру выдает?
Я просто сигнал взял со входа триггера внутри приемника, я могу его легко инвертировать и подтянуть к 5 вольтам. Там питание триггера 3,3 .
Re: PPM энкодер на ...дуино
Сегодня ночью появилось время и я продолжил.
PHP код:
#include <TimerOne.h>
#include <TinyGPS.h>
#include <EEPROM.h>
#include <Servo.h>
volatile uint16_t timerCount;
#define BTNPIN 2 //Входной сигнал PPM
int ppmImpuls[9]; // Массив импульсов для паузы и 8 каналов
int chImpuls[9] = {1000, 100, 100, 100, 100, 100, 100, 100, 100}; // Массив средних значений для паузы и 8 каналов
int chanel = 0 ; // Номер канала
int minImpuls = 45 ; // Минимальный импульс (450 us)
int maxImpuls = 155; // Максимальный импульс (1550 us)
int minPausa = 500; // Минимальная пауза (5000 us)
int maxPausa = 1300; // Максимальная пауза (13000 us)
Servo servo1;
Servo servo2;
void setup()
{
servo1.attach(37);
servo2.attach(36);
servo1.writeMicroseconds(1500); // устанавливает привод в среднее положение
servo2.writeMicroseconds(1500); // устанавливает привод в среднее положение
Serial.begin(115200);
pinMode (BTNPIN, INPUT);
Timer1.initialize(10);
Timer1.attachInterrupt(callback);
attachInterrupt(0, impDown, RISING);
}
void loop()
{
for (int i=0; i <= 8; i++)
{
chImpuls[i] = (4 * chImpuls[i] + ppmImpuls[i]) / 5 ; // усреднение 3 импульсов
//Serial.print(i); Serial.print("=");
//Serial.print(chImpuls[i]); Serial.print(" ");
}
Serial.println("");
//delay (200);
servo1.writeMicroseconds(chImpuls[1]*10);
servo2.writeMicroseconds(chImpuls[2]*10);
}
void callback() { timerCount++; } //--------- Счетчик------------
void impUp() //---------- Функция обработки положительного импульса
{
detachInterrupt(0);
timerCount=0;
attachInterrupt(0, impDown, RISING);
}
void impDown() // Функция обработки отрицательного импульса
{
int ppm = timerCount;
detachInterrupt(0);
if( ppm > minPausa ) { chanel=0 ; } else { chanel ++ ; }
ppmImpuls[chanel] = ppm ;
attachInterrupt(0, impUp, FALLING);
}
Файл-сафе теперь нужно реализовывать.
Что можно сделать с контролем над сигналом, шум подвешивает порт. Также перестают сервы следить за положением стиков. Резет при вкл. передатчике, все работает, но до выключения передатчика.
Re: PPM энкодер на ...дуино
Нужно делать программный фильтр шума.
Самый простой способ : сделать три, четыре или пять замеров длительности периода и считать что это достоверный сигнал.