Помогите решить задачу

Контроллеры, драйверы, датчики, управляющие устройства.
Аватара пользователя
niksooon
Мастер
Сообщения: 2144
Зарегистрирован: 23 июн 2014, 23:18
Репутация: 1207
Откуда: Кашира
Контактная информация:

Помогите решить задачу

Сообщение niksooon »

Парни,нуждаюсь в вашей помощи для решения вот такой проблемы-
Задача состоит в следующем- имеется аппаратура управления для rc моделей
радио.jpg
радио.jpg (7.68 КБ) 3594 просмотра
и необходимо её заставить управлять пропорциональным гидрораспределителем
гидрораспределитеоь.png
гидрораспределитеоь.png (18.01 КБ) 3594 просмотра
у которого две катушки двигают золотником....


Далее.....на выходе с аппаратуры имеем вот такой сигнал
servo-signal-pdm.png (3604 просмотра) <a class='original' href='./download/file.php?id=119344&mode=view' target=_blank>Загрузить оригинал (18.6 КБ)</a>
при нейтральном положении джойстика длительность импульса 1500мкс ,а в крайних 500 и 2500мкс

Ну собственно сам нубский вопрос-как на ардуине сделать так чтобы при изменении задающего сигнала от 1500 до 2500мкс активным был один pwm выход ардуины (и србственно pwm на этом выходе менялся от 0 до 100)
А при изменении сигнала от 1500 до 500 мкс в работу вступал другой pwm выход ,ну и разумеется что при среднем положении джойстика (1500мкс) на обоих выходах было по нулям.......
который день ищу примеры скетчей ,но пока ничего похожего нет...........
Последний раз редактировалось niksooon 30 авг 2017, 16:27, всего редактировалось 2 раза.
Сделанное правильно — красиво. Если сделанное тебе не нравится — то и работать оно будет хреново. Перевари, пересверли, выпили заново — ну, или хотя бы покрась.
Аватара пользователя
selenur
Почётный участник
Почётный участник
Сообщения: 4605
Зарегистрирован: 21 авг 2013, 19:44
Репутация: 1622
Настоящее имя: Сергей
Откуда: Новый Уренгой
Контактная информация:

Re: Помогите решить задачу

Сообщение selenur »

Если в Си разбираешься, вот пример скреча ардуиновского, к которому подключен дисплей по I2c, энкодер, и датчик холла.
Энкодером управляется выход PWM, на 11 пине.

Код: Выделить всё

#include <OLED_I2C.h>

/*
Использование выводов
Analog A4 - SDA oled display
Analog A5 - SCL oled display
Digital 11 - PWM out
Digital 5,6 - enconder AB
Digital 2 - (int0) 


*/


OLED  myOLED(SDA, SCL, 8);

extern uint8_t SmallFont[];
extern uint8_t MediumNumbers[];
extern uint8_t BigNumbers[];

/* Пины, к которым подключен энкодер */
enum { ENC_PIN1 = 5, ENC_PIN2 = 6 };

// для подсчета пришедших тактов
int countTick = 0;

// для хранения скорости вращения
int rpmold = 0;
int rpm = 0;

int pin = 13;
volatile int state = LOW;

uint8_t i=0;

void setup()
{
  // отключим прерывания
  noInterrupts();           // disable all interrupts
  
  //подключение енкондера
  pinMode(ENC_PIN1, INPUT);
  pinMode(ENC_PIN2, INPUT);  

  // инициализация дисплея
  myOLED.begin();
  myOLED.setFont(SmallFont);
  
  // инициализация генерации ШИМ с применением таймера №2
  // настройка ШИМ - выхода, digital-11, PB3(OC2A)
  pinMode(11, OUTPUT); 
  TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
  TCCR2B = TCCR2B & 0b11111000 | 0x02;
  OCR2A = 0;
  OCR2B = 50;
  
  // Добавляем прерывание, по входящему импульсу, KWH interrupt attached to IRQ 1 = pin3
  pinMode(pin, OUTPUT);
  attachInterrupt(0, onPulse, RISING); //RISING
  // подключение прерывания по импульсу на 2-м пине
  
  // настройка 16-ти битного таймера, на переполнение
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;            // preload timer 65536-16MHz/256/2Hz - начальное значение отсчета
  TCCR1B |= (1 << CS12);    // 256 prescaler 
  TIMSK1 |= (1 << TOIE1);   // enable timer overflow interrupt
  
  
  // выведем первоначальные данные
    myOLED.setFont(MediumNumbers);
    myOLED.printNumF(i, 2, RIGHT, 0); //строка на желтом фоне
    myOLED.setFont(BigNumbers);
    myOLED.printNumI(rpm, RIGHT, 40); // стока на голубом фоне
    myOLED.update();
  
  // настроим скорость порта
  //Serial.begin(9600);
  
  // включим прерывания
  interrupts();             // enable all interrupts
}

/* Функция декодирования кода Грея, взятая с Википедии.
* Принимает число в коде Грея, возвращает обычное его представление.
*/
unsigned graydecode(unsigned gray)
{
 unsigned bin;

 for (bin = 0; gray; gray >>= 1)
    bin ^= gray;

 return bin;
}

int ppp = 0;

void loop()
{
  // digitalWrite(pin, state);

  
 static uint8_t previous_code = 0; // предыдущий считанный код
 
 /* gray_code - считанное с энкодера значение
  * code - декодированное значение
  */
 uint8_t gray_code = digitalRead(ENC_PIN1) | (digitalRead(ENC_PIN2) << 1),
         code = graydecode(gray_code);
 
 
 uint8_t needRefresh = 0;
 
 /* Если считался нуль, значит был произведён щелчок ручкой энкодера */
 if (code == 0)
 {
   /* Если переход к нулю был из состояния 3 - ручка вращалась
    * по часовой стрелке, если из 1 - против.
    */
   if (previous_code == 3)
   {
     //Serial.println("->");     
     if (i<245) i+=1;
     OCR2A = i;      
   }
   else if (previous_code == 1)
   {
     //Serial.println("<-");     
     if (i>=10) i-=1;
     OCR2A = i; 
   }    
   
   needRefresh = 1;
   
 }
 
 if (rpmold != rpm)
 {
   needRefresh = 1;
   rpmold = rpm;
 }
 
 if (ppp >100)//needRefresh
 {
    //myOLED.clrScr();
    //myOLED.setFont(MediumNumbers);
    //myOLED.printNumF(i, 2, RIGHT, 0); //строка на желтом фоне
    
    myOLED.clrScr();
    
    myOLED.setFont(MediumNumbers);
    myOLED.printNumI(i, LEFT, 0); //строка на желтом фоне енкондер
    
    myOLED.setFont(MediumNumbers);
    myOLED.printNumI(rpm, RIGHT, 0); //строка на желтом фоне енкондер
    
    int ttt = rpm *60;
    
    myOLED.setFont(BigNumbers);
    myOLED.printNumI(ttt, RIGHT, 40); // стока на голубом фоне
    
    myOLED.update();
   
     needRefresh = 0;
     ppp = 0;
 }

 
 /* Сохраняем код и ждём 1 мс - вполне достаточно опрашивать энкодер
  * не более 1000 раз в секунду.
  */
 previous_code = code;
 delay(1);
 
 ppp++;
}


// прерывание от таймера
ISR(TIMER1_OVF_vect)
{
  countTick = 62500;
  //rpm = 0; // если произошло переполнение, значит нет вращения
  
  //TCNT1 = 0;            // preload timer
  //тут произведем вычисления скорости

//rpm++;

}


// прерывание по пришедшему импульсу
void onPulse()
{
  //state = !state;

  
  countTick = TCNT1; 
  TCNT1 = 0; //переапуск таймера
  
  rpm = 31250 / countTick;
  //rpm = (31250 / countTick) * 60;  
}


Мой сайт: http://selenur.ru
Исходники моих программ: https://github.com/selenur
Instagram https://www.instagram.com/zheigurov/
Аватара пользователя
Taganrog
Мастер
Сообщения: 1238
Зарегистрирован: 15 апр 2015, 16:32
Репутация: 284
Настоящее имя: Евгений
Откуда: Брянск
Контактная информация:

Re: Помогите решить задачу

Сообщение Taganrog »

Вроде несложно, делай захват импульса таймером он аппаратно посчитает длительность. Формируй ШИМ на другой лапе .
кусок кода с подсчетот:

Код: Выделить всё

  //************       настройка таймера-счётчика 1         ******* подсчитывает длительность между импульсами
  TCCR1A = 0; 
  TCCR1B = 0; 
  TCNT1 = 0; // начальное значение
  TIMSK1 = (1<<ICIE1)|(1<<TOIE1);  //разрешаем прерывание по захвату сигнала на 8 ноге и по переполнению таймера
  TCCR1B = (1<<ICNC1)|(1<<ICES1)|(1<<CS10);  //включаем шумоподавление и  установим делитель на 1 

}







ISR (TIMER1_CAPT_vect) { //прерывание  входящий сигнал на 8 ноге мега328
  tic_rpm = (err_rpm*65536)+ICR1; //сохраняем значения счетчика (количество тиков между импульсами) 
  impuls=1; // флаг прихода нового импульса
  TCNT1=0;  // сбрасываем регистр таймера
  err_rpm=0; // отменяем ошибку. Импульсы присутствуют. 
}   
ISR (TIMER1_OVF_vect) { //прерывание для счёта по переполнению uint
  err_rpm ++; // количество переполненй 
  if (err_rpm>15){  // если долго нет импульса всеравно тикаем для организации расчетов
    err_rpm=0;
    impuls_off=1;// флаг долгово отсутствия импульса
  }
}
Аватара пользователя
niksooon
Мастер
Сообщения: 2144
Зарегистрирован: 23 июн 2014, 23:18
Репутация: 1207
Откуда: Кашира
Контактная информация:

Re: Помогите решить задачу

Сообщение niksooon »

Спасибо ,пищу для размышлений подкинули.........
а вот такой еще вопрос как примерно может выглядить скетч ежели на какой либо аналоговый вход подцепить потенциометр (джойстик)? что бы при его среднем положении на обоих выходах pwm было по 0 ,а при перемещении(джойстика) вверх активировался первый pwm (и работал в диапазоне от 0 до 100%) а при движении джойстика вниз активировался второй(и тоже от 0 до 100%) ?
ну и дрейф нуля при этом тоже не мешало бы програмно откорректировать...... ???
ПЫ Сы ,с ардуинкой дел ранее не имел , приедет буквально завтра -послезавтра, пока пытаюсь хоть немного на примерах кода разобраться что к чему...........
Сделанное правильно — красиво. Если сделанное тебе не нравится — то и работать оно будет хреново. Перевари, пересверли, выпили заново — ну, или хотя бы покрась.
SVP
Мастер
Сообщения: 6140
Зарегистрирован: 19 дек 2012, 15:49
Репутация: 884
Откуда: Москва
Контактная информация:

Re: Помогите решить задачу

Сообщение SVP »

Читаешь АЦП, потом наружу устанавливаешь нужный pwm.
Немного непонятно в чем конкретно проблема.
Аватара пользователя
selenur
Почётный участник
Почётный участник
Сообщения: 4605
Зарегистрирован: 21 авг 2013, 19:44
Репутация: 1622
Настоящее имя: Сергей
Откуда: Новый Уренгой
Контактная информация:

Re: Помогите решить задачу

Сообщение selenur »

При подключении переменного резистора, ардуина при считывании данных с аналогового порта, в переменную записывает значение от нуля до 1024, а дальше вычисление настройки таймеров для генерации pwm сигнала.
Мой сайт: http://selenur.ru
Исходники моих программ: https://github.com/selenur
Instagram https://www.instagram.com/zheigurov/
sidor094
Мастер
Сообщения: 826
Зарегистрирован: 20 фев 2014, 09:13
Репутация: 81
Настоящее имя: Сергей
Откуда: Москва
Контактная информация:

Re: Помогите решить задачу

Сообщение sidor094 »

Можно поставить интегрирующую цепочку на выход джойстика и затем мерить ацп напряжение.
Аватара пользователя
niksooon
Мастер
Сообщения: 2144
Зарегистрирован: 23 июн 2014, 23:18
Репутация: 1207
Откуда: Кашира
Контактная информация:

Re: Помогите решить задачу

Сообщение niksooon »

Читаешь АЦП, потом наружу устанавливаешь нужный pwm.
Немного непонятно в чем конкретно проблема.
ну нуб я в этом,посему и воспрошаю....... ...
а всё же При подключении переменного резистора, ардуина при считывании данных с аналогового порта, в переменную записывает значение от нуля до 1024 это как бы понятно ,а как должен выглядить код чтобы при изменении значения на каком либо аналоговом входе с 512 до 1024 выход №1 pwm менялся от 0 до 100 % и наоборот при изменении сигнала на аналоговом входе от 512 до 0 на выходе №2 pwm уровень сигнала выростал от 0 до 100 %
Нужно всего то пара другая строк для примера для того чтоб понять как сие надо правильно прописывать............
Сделанное правильно — красиво. Если сделанное тебе не нравится — то и работать оно будет хреново. Перевари, пересверли, выпили заново — ну, или хотя бы покрась.
Аватара пользователя
Taganrog
Мастер
Сообщения: 1238
Зарегистрирован: 15 апр 2015, 16:32
Репутация: 284
Настоящее имя: Евгений
Откуда: Брянск
Контактная информация:

Re: Помогите решить задачу

Сообщение Taganrog »

Попробуй так:

Код: Выделить всё


void setup() {
  pinMode(ledPin, OUTPUT);  //делаем ножку выходом
}

void loop() {
 
  sensorValue = analogRead(0); // читаем аналоговое значение

  sensor=map(sensorValue,0,1023,0,255); // масштабируем из 0-1023 пропорционально до 0-255
  analogWrite(ledPin,sensor); // задаем шим на ножке со скважностью равной sensor
  


}
Аватара пользователя
niksooon
Мастер
Сообщения: 2144
Зарегистрирован: 23 июн 2014, 23:18
Репутация: 1207
Откуда: Кашира
Контактная информация:

Re: Помогите решить задачу

Сообщение niksooon »

По представленному выше все понятно, и в примерах я такое нашел, но мне надо немного по другому -чтобы при изменении значения на аналоговом входе с 512 до 1024 выход №1 pwm менялся от 0 до 100 % и наоборот при изменении сигнала на этом же аналоговом входе от 512 до 0 на выходе №2 pwm уровень сигнала выростал от 0 до 100 %
Сделанное правильно — красиво. Если сделанное тебе не нравится — то и работать оно будет хреново. Перевари, пересверли, выпили заново — ну, или хотя бы покрась.
Аватара пользователя
selenur
Почётный участник
Почётный участник
Сообщения: 4605
Зарегистрирован: 21 авг 2013, 19:44
Репутация: 1622
Настоящее имя: Сергей
Откуда: Новый Уренгой
Контактная информация:

Re: Помогите решить задачу

Сообщение selenur »

Тут всё очень просто, имеем переменную П1 которая меняется от 0 до 1024, а П2, и П3 собственно значения которые меняются в нужную сторону.
Алгоритм такой:

Код: Выделить всё

Если П1 <= 512 Тогда П2 = 512 - П1
Иначе П2 = 0

Если П1 >= 512 Тогда П3 = П1 - 512
Иначе П3 = 0
В результате чего пока значение П1 меняется от нуля до 512, значение П2 меняется от 512 до нуля, а П3 пока равно нулю.
После того как значение П1 стало увеличиваться от 512 до до 1024, значение П2 продолжает иметь значение 0, а в П3 значение меняется от нуля до 512.

Как значение от нуля до 512 пере-масштабировать в значение от нуля до 100 для П2 и П3 думаю понятно :-)
Мой сайт: http://selenur.ru
Исходники моих программ: https://github.com/selenur
Instagram https://www.instagram.com/zheigurov/
Аватара пользователя
niksooon
Мастер
Сообщения: 2144
Зарегистрирован: 23 июн 2014, 23:18
Репутация: 1207
Откуда: Кашира
Контактная информация:

Re: Помогите решить задачу

Сообщение niksooon »

вот что то намудрил со сторонней помощью)

Код: Выделить всё

#define Ppin A0   // сюда подключена средняя нога потенциометра
const int APin = 3;         // пин подключения pwm выхода A
const int BPin = 9;         // пин подключения pwm выхода B
const int Dead = 200;    // ширина мертвой зоны в центре потенциометра
 
int Pot;      //значение с потенциометра
int Aval;   //значение для PWM-выхода A
int Bval;   //значение для PWM-выхода B
int Lo;      //нижняя граница
int Hi;      //верхняя граница
 
 
 
void setup() {
//  Serial.begin(9600);
 
//границы верхней и нижней зоны
Lo = (1024-Dead) / 2;
Hi = Lo+Dead;
 
}
 
 
 
void loop() {
 
//читаем сигнал с потенциометра
Pot = analogRead(Ppin);
 
//нижняя половина: работаем по выходу А
if (Pot <= Lo)
{ Aval = map(Pot,   0,Lo,     255,0);
   Bval = 0;
}
 
else if (Pot >= Hi)   //верхняя половина: работаем по выходу B
{ Aval = 0;
   Bval = map(Pot,   Hi,1023,    0,255);
}
 
else   //мертвая зона в центре: обнуляем оба выхода А и В
{ Aval = 0;
   Bval = 0;
};
 
//записываем полученные значения в PWM-выходы
analogWrite(APin, Aval); 
analogWrite(BPin, Bval); 
 
}
даже работает правильно вроде как.......
Гляньте плиз в самом верху правильно ли пины и прочее бла-бла прописаны?
Сделанное правильно — красиво. Если сделанное тебе не нравится — то и работать оно будет хреново. Перевари, пересверли, выпили заново — ну, или хотя бы покрась.
Аватара пользователя
selenur
Почётный участник
Почётный участник
Сообщения: 4605
Зарегистрирован: 21 авг 2013, 19:44
Репутация: 1622
Настоящее имя: Сергей
Откуда: Новый Уренгой
Контактная информация:

Re: Помогите решить задачу

Сообщение selenur »

В процедуре Setup обычно прописывают инициализацию портов, какой из пинов будет вход/выход, хотя похоже обращения к пинам автоматом добавило эту инициализацию..
Мой сайт: http://selenur.ru
Исходники моих программ: https://github.com/selenur
Instagram https://www.instagram.com/zheigurov/
Аватара пользователя
niksooon
Мастер
Сообщения: 2144
Зарегистрирован: 23 июн 2014, 23:18
Репутация: 1207
Откуда: Кашира
Контактная информация:

Re: Помогите решить задачу

Сообщение niksooon »

вот и я пробывал pinMode как положено поназначить ,а компилятор ругаеццо............. если все работает мож так и оставить? и не забивать себе голову?
Сделанное правильно — красиво. Если сделанное тебе не нравится — то и работать оно будет хреново. Перевари, пересверли, выпили заново — ну, или хотя бы покрась.
Аватара пользователя
Taganrog
Мастер
Сообщения: 1238
Зарегистрирован: 15 апр 2015, 16:32
Репутация: 284
Настоящее имя: Евгений
Откуда: Брянск
Контактная информация:

Re: Помогите решить задачу

Сообщение Taganrog »

niksooon писал(а):пробывал pinMode как положено поназначить
На что ругается то?
Ацп стабильнее работает если в сетапе прописать подтягивание ножки к питанию таким образом:
pinMode(A1,INPUT_PULLUP);
Аватара пользователя
niksooon
Мастер
Сообщения: 2144
Зарегистрирован: 23 июн 2014, 23:18
Репутация: 1207
Откуда: Кашира
Контактная информация:

Re: Помогите решить задачу

Сообщение niksooon »

ну вот к примеру еще код для моих нужд

Код: Выделить всё

//номера пинов, куда подключены потенциометры А и В
#define potApin A0            // потенциометр A
#define potBpin A1            // потенциометр В
 
//номера пинов, куда подключены pwm выходы A и В
const int pwmApin = 3;         // pwm выход A
const int pwmBpin = 9;         // pwm выход B
 
//номер пинов, куда подключены дискретные входы
const int btnPin = 5;            //кнопка СТАРТ
const int snsPin = 6;            //датчик
 
int potA=0;        //значение с потенциометра A
int potB=0;        //значение с потенциометра B
int pwmA=0;     //значение для PWM-выхода A
int pwmB=0;     //значение для PWM-выхода B
boolean btn = false;    //состояние кнопки
boolean sns = false;    //состояние датчика
boolean run = false;    //флаг активности перемещения
 
//---------------------------------------------------------------------------------------------------
void setup() {
//  Serial.begin(9600);
pinMode(A0,INPUT_PULLUP);
pinMode(A1,INPUT_PULLUP); 
//конфигурируем пины, куда подключена дискретные входы
pinMode(btnPin,INPUT)
pinMode(snsPin,INPUT)
 
}
 
//---------------------------------------------------------------------------------------------------
void loop() {
 
//читаем дискретные входы
btn = digitalRead(btnPin);   //кнопка СТАРТ
sns = digitalRead(snsPin);   //датчик
 
//старт движения по нажатию кнопки,  стоп движения по срабатыванию концевика
if ((btn == HIGN)  && (run == LOW)  &&   (sns == HIGH))      run = HIGH;
if ((run == HIGH)  && (sns == LOW))       run = LOW;
 
//формируем сигналы для pwm-выходов
//если выполняется перемещение, то передаем на pwm-выходы сигнал с потенциометра
//если же остановлен, то обнуляем оба выхода А и В
if (run == HIGH)
{ //читаем сигналы с потенциометров
   potA = analogRead(potApin);
   potB = analogRead(potBpin);
 
  //масштабируем сигнал от потенциометра
   pwmA = map(potA,   0,1023,     0,255);
   pwmB = map(potB,   0,1023,     0,255);
}
else   
{ pwmA = 0;
   pwmB = 0;
};
 
//записываем полученные значения в PWM-выходы
analogWrite(pwmApin, pwmA); 
analogWrite(pwmBpin, pwmB); 
 
}
вставил
pinMode(A0,INPUT_PULLUP);
pinMode(A1,INPUT_PULLUP); и нате вам пожалуйста , ругаетссо
упс.png (3300 просмотров) <a class='original' href='./download/file.php?id=119613&mode=view' target=_blank>Загрузить оригинал (55.2 КБ)</a>
че ему надоть, иль что не так мне пока соображалки не хватает........
прошу пардону......причина в другом............
Сделанное правильно — красиво. Если сделанное тебе не нравится — то и работать оно будет хреново. Перевари, пересверли, выпили заново — ну, или хотя бы покрась.
SVP
Мастер
Сообщения: 6140
Зарегистрирован: 19 дек 2012, 15:49
Репутация: 884
Откуда: Москва
Контактная информация:

Re: Помогите решить задачу

Сообщение SVP »

niksooon писал(а):че ему надоть, иль что не так мне пока соображалки не хватает........
Вы то что красным снизу написано читали ?
Что там написано ?
Аватара пользователя
selenur
Почётный участник
Почётный участник
Сообщения: 4605
Зарегистрирован: 21 авг 2013, 19:44
Репутация: 1622
Настоящее имя: Сергей
Откуда: Новый Уренгой
Контактная информация:

Re: Помогите решить задачу

Сообщение selenur »

После каждой строчки с кодом следует использовать символ ";" вот на его отсутствие и ругается.
Мой сайт: http://selenur.ru
Исходники моих программ: https://github.com/selenur
Instagram https://www.instagram.com/zheigurov/
Аватара пользователя
niksooon
Мастер
Сообщения: 2144
Зарегистрирован: 23 июн 2014, 23:18
Репутация: 1207
Откуда: Кашира
Контактная информация:

Re: Помогите решить задачу

Сообщение niksooon »

туплю блин ; запамятовал поставить...........
Сделанное правильно — красиво. Если сделанное тебе не нравится — то и работать оно будет хреново. Перевари, пересверли, выпили заново — ну, или хотя бы покрась.
AVK74
Почётный участник
Почётный участник
Сообщения: 1854
Зарегистрирован: 02 июл 2013, 09:03
Репутация: 335
Откуда: Уфа
Контактная информация:

Re: Помогите решить задачу

Сообщение AVK74 »

Делать что то критичное по времени из под ардуины довольно таки странно ИМХО.
Такое нужно делать на прерываниях и таймерах.
Четко понимаю что в какое время происходит.
Используйте CodeVision+Proteus хотя бы.
Нисколько не сложнее, но гораздо прозрачнее и никаких непоняток.
Ответить

Вернуться в «Электроника»