Написание кода передатчика и приемника (для подводного аппарата) за вознаграждение

wenom86
Offline
Зарегистрирован: 04.11.2012

Здравствуйте. У меня в разработке проект подводного телеуправляемого аппарата. Не коммерция, чисто хобби. Посмотреть о чем речь можно в этой теме: http://forum.rcdesign.ru/f130/thread335111.html 

Ищу исполнителя для написания программного кода передатчика и приемника команд управления (вперед, назад, вращение на месте, включение и выключение источников света, управление манипулятором и т.д.)  Передача данных будет происходить по RS485. Аппаратная часть передатчика и приемника изготовлены и работают.

Предполагаю, что написание программ будет поэтапным. Сначала добавим функции управления освещением, затем движением, манипулятором и т.д. Оплата за работу так-же будет поэтапна. За дополнительную функцию программы (мои прихоти) оплата по договоренности. Предпочтение работать с одним человеком или группой, которые пишут и по необходимости наращивают программу. 

Для начала необходимо написать код передатчика, который отправлял - бы в порт Serial в каналы E/F/G/H информацию о нажатии каждой для своего канала тактовой (нефиксируемой) кнопки. Допустим:

a) Включили передатчик - в порт отправляются "0"

б) Нажали и отпустили кнопку - в порт отправляются "1"

в) Нажали и отпустили еще раз - отправляются "0"

Пожелание по коду: (во время нажатия и последующего удержания (пускай даже на полсекунды) кнопки информация, отправляемая в порт не должна меняться. Допустим в порт отправляются нули, при нажатии кнопки в порт или сразу, или после отпускания кнопки должны отправиться единицы, а не 0-1-0-1 и т.д.)

Имеется код, который был написан ранее (если он подходит - отталкиваться необходимо от него)

001// Передатчик команд управления v5.1 (23 дек 2014г)
002// Органы управления - 4 переменника, 9 кнопок.
003// Механизмы оповещения и индикации - 1мотор-вибратор, 1 светодиод
004 
005//Цель:
006//при нажатии кнопки 1,2,3,4 отправить в сериал-порт информацию о текущем значении.(0 или 1) (канал с фиксацией значения при нажатии)
007//при нажатии кнопки 11 отправить в сериал-порт информацию о текущем значении.(0 или 1) (кнопка без фиксации значения)
008//при вращении ручки потенциометра 1-4 обработать значения с них и отправить данные в порт для каждого двигателя. (от -100 до 100, нейтральное положение - "0")
009//по каналу управления манипулятором передаются значения (от -100 до 0 и от 0 до 100)
010//по каналу управления наклоном камеры передаются значения (от 0 до 180)
011 
012#define ANALOG_IN0  0 // Порт, к которому подключен переменный резистор 1
013#define ANALOG_IN1  1 // Порт, к которому подключен переменный резистор 2
014#define ANALOG_IN2  2 // Порт, к которому подключен переменный резистор 3
015#define ANALOG_IN3  3 // Порт, к которому подключен переменный резистор 4
016 
017int LeftStickX = 0; // переменная Левого стика - ось X (вниз-вверх)
018int LeftStickY = 1; // переменная Левого стика - ось Y (пока неиспользуется)
019int RightStickX = 2;// переменная Правого стика - ось X (вперед-назад)
020int RightStickY = 3;// переменная Правого стика - ось Y (влево-вправо)
021 
022int Pin2 = 2;    //пин 2 используется для включения передачи данных по rs485
023int Knopka1 = 10; //кнопка1 подключена к 3 цифровому контакту (освещение 1) (фиксируемая)
024int Knopka2 = 7; //кнопка2 подключена к 4 цифровому контакту (освещение 2) (фиксируемая)
025int Knopka3 = 8; //кнопка3 подключена к 5 цифровому контакту (освещение 3) (фиксируемая)
026int Knopka4 = 6; //кнопка4 подключена к 6 цифровому контакту (освещение 4) (фиксируемая)
027int Knopka7 = 11; //кнопка7 подключена к 7 цифровому контакту (манипулятор - сжать) (нефиксируемая)
028int Knopka8 = 5; //кнопка8 подключена к 8 цифровому контакту (манипулятор - разжать) (нефиксируемая)
029int Knopka9 = 4; //кнопка9 подключена к 9 цифровому контакту (камера - вверх)
030int Knopka10 = 3; //кнопка10 подключена к 10 цифровому контакту (камера - вниз)
031int Knopka11 = 9; //кнопка11 подключена к 11 цифровому контакту (резервная) (нефиксируемая)
032int MotorPin = 12; //моторы в пульте управления подключены через транзистор к 12 цифровому контакту (пока никак не используются)
033//int LedPin = 13; // инициализация светодиода, светодиод в пульте управления подключен к 13 цифровому контакту
034int KanalMotoraLevogoGor, KanalMotoraPravogoGor, KanalMotoraPerVert, KanalMotoraZadVert;
035int PinUpr1 = 13;
036int flag1, flag2, flag3, flag4 = 0;
037int KanalKn1, KanalKn2, KanalKn3, KanalKn4 = 0;
038 
039void setup() {
040  Serial.begin(115200);              // скорость передачи данных в мониторе порта = 115200.
041  // Инициализируем цифровые входы/выходы с 3 по 11 в режиме входов.
042  pinMode(Knopka1, INPUT);           // назначить выводу порт ввода
043  digitalWrite(Knopka1, HIGH);       // активируем подтягивающий резистор 20ком к питанию.
044  pinMode(Knopka2, INPUT);           //.......
045  digitalWrite(Knopka2, HIGH);
046  pinMode(Knopka3, INPUT);       
047  digitalWrite(Knopka3, HIGH);
048  pinMode(Knopka4, INPUT);       
049  digitalWrite(Knopka4, HIGH);
050  pinMode(Knopka7, INPUT);       
051  digitalWrite(Knopka7, HIGH);
052  pinMode(Knopka8, INPUT);       
053  digitalWrite(Knopka8, HIGH);
054  pinMode(Knopka9, INPUT);       
055  digitalWrite(Knopka9, HIGH);
056  pinMode(Knopka10, INPUT);       
057  digitalWrite(Knopka10, HIGH);
058  pinMode(Knopka11, INPUT);       
059  digitalWrite(Knopka11, HIGH);
060  pinMode(PinUpr1, OUTPUT);
061}
062 
063 
064 
065 
066void loop()
067
068// -----------------НАЧАЛО СЧИТЫВАНИЙ ПОКАЗАНИЙ СТИКОВ И ОТПРАВКА ЗНАЧЕНИЙ В ПОРТ-----------------
069  LeftStickX = analogRead (ANALOG_IN0);  
070  LeftStickY = analogRead (ANALOG_IN1);  
071  RightStickX = analogRead (ANALOG_IN2);
072  RightStickY = analogRead (ANALOG_IN3);
073  Serial.print ("LeftStick-X ");
074  Serial.println (LeftStickX);
075  Serial.print ("LeftStick-Y ");
076  Serial.println (LeftStickY);
077  Serial.print ("RightStick-X ");
078  Serial.println (RightStickX);
079  Serial.print ("RightStick-Y ");
080  Serial.println (RightStickY);
081  Serial.println ("---------");
082// -----------------КОНЕЦ СЧИТЫВАНИЙ ПОКАЗАНИЙ СТИКОВ И ОТПРАВКА ЗНАЧЕНИЙ В ПОРТ-----------------  
083   
084 
085// -----------------НАЧАЛО ТЕСТА ПРОВЕРКИ РАБОТЫ КНОПОК (при каждом нажатии на кнопку вспыхивает светодиод)( в окончательном коде закомментировать все строчки-----------------
086// if (digitalRead(Knopka1) == HIGH && digitalRead(Knopka2) == HIGH && digitalRead(Knopka3) == HIGH && digitalRead(Knopka4) == HIGH &&  digitalRead(Knopka7) == HIGH && digitalRead(Knopka8) == HIGH && digitalRead(Knopka9) == HIGH && digitalRead(Knopka10) == HIGH && digitalRead(Knopka11) == HIGH )
087// { digitalWrite (LedPin, LOW);
088// }
089// else { digitalWrite (LedPin, HIGH);
090// }
091// -----------------КОНЕЦ ТЕСТА ПРОВЕРКИ РАБОТЫ КНОПОК-----------------
092   
093   
094// -----------------НАЧАЛО ПРЕОБРАЗОВАНИЯ ДАННЫХ С КНОПОК И ПЕРЕМЕННИКОВ В ФОРМАТ ДЛЯ ПЕРЕДАЧИ ПО SERIAL-----------------   
095// (-) канал вперед-назад-влево-вправо)
096     RightStickX = constrain(RightStickX, 20, 1000);
097     RightStickY = constrain(RightStickY, 20, 1000);
098     KanalMotoraLevogoGor = map(RightStickX, 20, 1000, 100, -100);
099     KanalMotoraPravogoGor = map(RightStickX, 20, 1000, 100, -100);    
100      
101// (+) начало обработки канала погружения-всплытия)
102     LeftStickX = constrain(LeftStickX, 20, 1000);
103     KanalMotoraPerVert = map(LeftStickX, 20, 1000, 100, -100);
104     KanalMotoraZadVert = map(LeftStickX, 20, 1000, 100, -100);
105     
106// (+) канал кнопки 1
107    if(digitalRead(Knopka1)==LOW&&flag1==0) //если кнопка нажата и переменная flag равна 0 , то ...
108      { digitalWrite(PinUpr1,!digitalRead(PinUpr1));  flag1=1; }                 
109    if(digitalRead(Knopka1)==HIGH&&flag1==1) //если кнопка нажата повторно и переменная flag равна 1 ,то ...
110      { flag1=0; }  //обнуляем переменную flag
111    if(digitalRead(PinUpr1)==!HIGH) //если кнопка не нажата и переменная flag равна 1 , то ...
112      { KanalKn1=1;}
113    if(digitalRead(PinUpr1)==!LOW) //если кнопка не нажата и переменная flag равна 0 , то ...
114      { KanalKn1=0;}
115       
116 
117 
118  // -----------------КОНЕЦ ПРЕОБРАЗОВАНИЯ ДАННЫХ С КНОПОК И ПЕРЕМЕННИКОВ В ФОРМАТ ДЛЯ ПЕРЕДАЧИ ПО SERIAL-----------------
119    
120    
121  // -----------------НАЧАЛО ПЕРЕДАЧИ ПРЕОБРАЗОВАННЫХ И ОБРАБОТАННЫХ ДАННЫХ ПО SERIAL-----------------
122  digitalWrite (Pin2, HIGH);                // активация передачи данных по rs485
123  Serial.print('A');                        //метка начала передачи значения канала "а"
124  Serial.println(KanalMotoraLevogoGor);     //.......
125  Serial.print('B');
126  Serial.println(KanalMotoraPravogoGor);     
127  Serial.print('C');
128  Serial.println(KanalMotoraPerVert);     
129  Serial.print('D');
130  Serial.println(KanalMotoraZadVert);     
131  Serial.print('E');
132  Serial.println(digitalRead(KanalKn1));
133  Serial.print('F');
134  Serial.println(digitalRead(KanalKn2)); 
135  Serial.print('G');
136  Serial.println(!digitalRead(Knopka3));  
137  Serial.print('H');
138  Serial.println(!digitalRead(Knopka4)); 
139  Serial.print('I');
140  Serial.println(!digitalRead(Knopka7));             
141  Serial.print('J');
142  Serial.println(!digitalRead(Knopka8));            
143  Serial.print('K');
144  Serial.println(!digitalRead(Knopka9)); 
145  Serial.print('L');
146  Serial.println(!digitalRead(Knopka10));
147  Serial.print('M');
148  Serial.println(!digitalRead(Knopka11));  
149  Serial.println("------------------END------------------");  //конец передачи.
150  // -----------------КОНЕЦ ПЕРЕДАЧИ ПРЕОБРАЗОВАННЫХ И ОБРАБОТАННЫХ ДАННЫХ ПО SERIAL-----------------
151   
152  delay(10);
153  // delay(1000);   // Задержка в 1000 включается только при проверке работоспособности осей стиков в мониторе порта.
154                               // Для включения задержки необходимо раскомментировать строку
155                               // Просматривать значения можно в Мониторе порта
156                               // В рабочем режиме задержка нужно установить = 10
157}

 

 

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Добрый день!

Не совсем понятно задание. Из описания - все просто (даже элементарно), тем более у вас есть программа. В чем подвох?

wenom86
Offline
Зарегистрирован: 04.11.2012

Дело в том, что катастрофически не хватает времени на изучение программирования. И так хотел запустить аппарат летом 2014, но загвоздка в программе была, хотел сам изучить, но дальше азов не продвинулся. Программа может пока легкая, только будет обрастать доп. Функциями. Подвоха нет, просто нужна помощь человеку-железячнику в программировании.

wenom86
Offline
Зарегистрирован: 04.11.2012

При нажатии на ссылку она не открывается. Чтобы открыть, необходимо стереть в конце ссылки 1 пробел.

 

Artur1985
Offline
Зарегистрирован: 19.02.2013

Добрый вечер.
Искал ответ по синхронизации передачи данных по RS485 и случайно увидел Ваше сообщение. Сам сейчас с другом делаем наброски по аналогичному проекту - проект подводного телеуправляемого аппарата. Приятно видеть, что не только нам лавры Кусто не дают уснуть:).

Тоже делаю на RS485 передачу управления, делаю в свободное время.

По коду

wenom86 пишет:

Имеется код, который был написан ранее (если он подходит - отталкиваться необходимо от него)

Не рекомендовал бы использовать данный код в готовом решении. 

Начнем с UART (Serial), лучше делать отправку и получение на прерываниях + передача байтами + кольцевой буфер, это уменьшит размер кода и сделает его более эффективным, без лишних задержек.

Более рациональное использование ресурсов позволит в будущем иметь запас по расширению, к примеру, для стабилизации при течении (акселерометр, гироскоп) и т.д. Тем более

wenom86 пишет:
Программа может пока легкая, только будет обрастать доп. Функциями.

Примерное описание, данной реализации с неплохим пояснением.

Крайне не желательно использовать delay в loop.

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

Проект как я понял, почти закончен. Но возможно, будет полезно использование Playstation joystick, вместо кнопок. Более подробно тут.

Будут вопросы, пишите.

 

 
Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Artur1985, а с вашими набросками можно познакомиться?

Artur1985
Offline
Зарегистрирован: 19.02.2013

Отчасти, увы нет времени их публиковать. Сейчас проходят тесты отдельные модули, работы еще много, в том числе и кодинга. 

Я пишу коды и разбераюсь с электроникой, мой друг механикой и корпусом.

Вот пару фото


Габариты 164*156*202мм.

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Меня, как волонтера, именно кодовая часть интересует.

Artur1985
Offline
Зарегистрирован: 19.02.2013

Тут все очень сильно зависит от конкретного Rov. К примеру, для классического Rov, данные идут с береговой станции на Rov, а телеметрия отображается на видео сигнале. К примеру на той же MAX7456. 

Я не стал изобретать велосипед и воспользовался проектом Multiwii, там хорошая схема передачи данных, простой протокол + проверенный IMU. Сейчас подпиливаю под собственные нужды протокол и думаю над синхронизации RS-485. У меня не классический Rov, данные идут в обе стороны. 
 

Gippopotam пишет:

Меня, как волонтера, именно кодовая часть интересует.

Готового решения у меня пока нет, делается в свободное время. 
Мое решение, без доработки использовать не получится. Да можно будет взять саму передачу данных, но протокол придется переписывать. Так как он будет заточен, под особенности моего Rov.

Artur1985
Offline
Зарегистрирован: 19.02.2013

Добрался до рабочего компа, как я говорил, лучше если Вы посмотрите код оригинала.
Вот мой код, по сути код от MultiWii, лишь изменена стилистика.
Так же начал вставлять комментарии.

UART.cpp
 

001/**********************************  Библиотеки  **************************************/
002#include "Arduino.h"
003 
004#include "UART.h"
005 
006#include "Def.h"
007 
008#include "Config.h"
009/**********************************  /Библиотеки  *************************************/
010 
011/**************************************************************************************/
012/*****************             Класс работы с UART               **********************/
013/**************************************************************************************/
014 
015// SerialHeadRX - буфер RX для хранения "головы масива"
016// SerialTailRX - буфер RX для хранения "хвоста масива"
017static volatile uint8_t SerialHeadRX[UARTNumber],SerialTailRX[UARTNumber];
018 
019// SerialBufferRX - буфер RX для хранения данных
020static uint8_t SerialBufferRX[RXBufferSize][UARTNumber];
021 
022// SerialHeadTX - буфер TX для хранения "головы масива"
023// SerialTailTX - буфер TX для хранения "хвоста масива"
024static volatile uint8_t SerialHeadTX[UARTNumber],SerialTailTX[UARTNumber];
025 
026// SerialBufferTX - буфер X для хранения данных
027static uint8_t SerialBufferTX[TXBufferSize][UARTNumber];
028 
029/// <summary>
030// Инициализируем и открываем UART порт
031/// </summary>
032/// <param name="port">Номер порта</param>
033/// <param name="baud">Скорость работы порта</param>
034void UARTOpen(uint8_t port, uint32_t baud)
035{
036  // U2X - Удвоение скорости обмена. Если этот разряд установлен в «1», коэффициент деления предделителя контроллера скорости передачи уменьшается с 16 до 8, удваивая тем самым скорость асинхронного обмена по последовательному каналу. В USART разряд U2X используется только при асинхронном режиме работы. В синхронном режиме он должен быть сброшен.
037  // UBRRL  и UBRRH - регистры скорости передачи  
038  // RXEN - Разрешение приема. При установке этого разряда в «1» разрешается работа приемника USART/UART и переопределяется функционирование вывода RXD.
039  // TXEN - Разрешение передачи. При установке этого разряда в «1» разрешается работа передатчика UART и переопределяется функционирование вывода TXD
040  // RXCIE - Разрешение прерывания по завершению приема. Если данный разряд установлен в «1», то при установке флага RXC регистра UCSRA генерируется прерывание.
041   
042  uint8_t h = ((F_CPU  / 4 / baud -1) / 2) >> 8;
043  uint8_t l = ((F_CPU  / 4 / baud -1) / 2);
044  switch (port)
045  {
046    #if defined(ArduinoProMini)
047      case 0: UCSR0A  = (1<<U2X0); UBRR0H = h; UBRR0L = l; UCSR0B |= (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0); break;
048    #endif
049    #if defined(ArduinoProMicro)
050      case 1: UCSR1A  = (1<<U2X1); UBRR1H = h; UBRR1L = l; UCSR1B |= (1<<RXEN1)|(1<<TXEN1)|(1<<RXCIE1); break;
051    #endif
052    #if defined(ArduinoMega)
053      case 0: UCSR0A  = (1<<U2X0); UBRR0H = h; UBRR0L = l; UCSR0B |= (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0); break;
054      case 1: UCSR1A  = (1<<U2X1); UBRR1H = h; UBRR1L = l; UCSR1B |= (1<<RXEN1)|(1<<TXEN1)|(1<<RXCIE1); break;
055      case 2: UCSR2A  = (1<<U2X2); UBRR2H = h; UBRR2L = l; UCSR2B |= (1<<RXEN2)|(1<<TXEN2)|(1<<RXCIE2); break;
056      case 3: UCSR3A  = (1<<U2X3); UBRR3H = h; UBRR3L = l; UCSR3B |= (1<<RXEN3)|(1<<TXEN3)|(1<<RXCIE3); break;
057    #endif
058  }
059}
060 
061/// <summary>
062// Сохраняем полученный байт в буфер RX для хранения данных
063/// </summary>
064/// <param name="data">Полученный байт</param>
065/// <param name="port">Номер порта</param>
066void StoreUartInBuf(uint8_t data, uint8_t portnum)
067{
068  // Получаем номер "головы масива" RX
069  uint8_t h = SerialHeadRX[portnum];
070  // Проверяем, увеличиваем номер "головы масива" RX головы на 1 и если номер "головы масива", станет равным или больше размера буфера, обнуляем переменную h в 0 
071  if (++h >= RXBufferSize)
072  {
073    h = 0;
074  }
075   
076  // Убрал для отладки
077  // Проверяем номер "головы масива" RX и номер "хвоста масива" RX если равен, это ошибка
078  if (h == SerialTailRX[portnum])
079  {
080    return;
081  }
082   
083  // Сохраняем полученный байт в буфер RX для хранения данных
084  SerialBufferRX[SerialHeadRX[portnum]][portnum] = data; 
085   
086  // Сохраняем новый номер "головы масива" RX
087  SerialHeadRX[portnum] = h;
088}
089 
090// Обработчик завершение приема по каналу USART
091#if defined(ArduinoProMini)
092  ISR(USART_RX_vect)  { StoreUartInBuf(UDR0, 0); }
093#endif
094#if defined(ArduinoProMicro)
095  ISR(USART1_RX_vect)  { StoreUartInBuf(UDR1, 1); }
096#endif
097#if defined(ArduinoMega)
098  ISR(USART0_RX_vect)  { StoreUartInBuf(UDR0, 0); }
099  ISR(USART1_RX_vect)  { StoreUartInBuf(UDR1, 1); }
100  ISR(USART2_RX_vect)  { StoreUartInBuf(UDR2, 2); }
101  ISR(USART3_RX_vect)  { StoreUartInBuf(UDR3, 3); }
102#endif
103 
104// Обработчик прерывания по опустошению буффера UART
105#if defined(ArduinoProMini) || defined(ArduinoMega)
106  #if defined(ArduinoProMini)
107  ISR(USART_UDRE_vect)
108  
109  #endif
110  #if defined(ArduinoMega)
111  ISR(USART0_UDRE_vect)
112  {
113  #endif
114    uint8_t t = SerialTailTX[0];
115    if (SerialHeadTX[0] != t)
116    {
117      if (++t >= TXBufferSize)
118      {
119        t = 0;
120      }
121      UDR0 = SerialBufferTX[t][0]; 
122      SerialTailTX[0] = t;
123    }
124     
125    if (t == SerialHeadTX[0])
126    {
127      UCSR0B &= ~(1<<UDRIE0);
128    }
129  }
130#endif
131#if defined(ArduinoMega) || defined(ArduinoProMicro)
132  ISR(USART1_UDRE_vect)
133  {
134    uint8_t t = SerialTailTX[1];
135    if (SerialHeadTX[1] != t)
136    {
137      if (++t >= TXBufferSize)
138      {
139        t = 0;
140      }
141      UDR1 = SerialBufferTX[t][1]; 
142      SerialTailTX[1] = t;
143    }
144    if (t == SerialHeadTX[1])
145    {
146      UCSR1B &= ~(1<<UDRIE1);
147    }
148  }
149#endif
150#if defined(ArduinoMega)
151  ISR(USART2_UDRE_vect)
152  {
153    uint8_t t = SerialTailTX[2];
154    if (SerialHeadTX[2] != t)
155    {
156      if (++t >= TXBufferSize) t = 0;
157      UDR2 = SerialBufferTX[t][2];
158      SerialTailTX[2] = t;
159    }
160    if (t == SerialHeadTX[2])
161    {
162      UCSR2B &= ~(1<<UDRIE2);
163    }
164  }
165  ISR(USART3_UDRE_vect)
166  {
167    uint8_t t = SerialTailTX[3];
168    if (SerialHeadTX[3] != t)
169    {
170      if (++t >= TXBufferSize)
171      {
172        t = 0;
173      }
174      UDR3 = SerialBufferTX[t][3];
175      SerialTailTX[3] = t;
176    }
177    if (t == SerialHeadTX[3])
178    {
179      UCSR3B &= ~(1<<UDRIE3);
180    }
181  }
182#endif
183 
184/// <summary>
185// Сохраняем отправляемый байт в буфер TX для хранения данных
186/// </summary>
187/// <param name="port">Номер порта</param>
188/// <param name="a">Отправляемый байт</param>
189void UARTSerialize(uint8_t port, uint8_t a)
190{
191  uint8_t t = SerialHeadTX[port];
192  if (++t >= TXBufferSize)
193  {
194    t = 0;
195  }
196  SerialBufferTX[t][port] = a;
197  SerialHeadTX[port] = t;
198}
199 
200/// <summary>
201// Отправляем данные по UART, включаем прерывание по опустошению буффера UART
202/// </summary>
203/// <param name="port">Номер порта</param>
204void UARTSendData(uint8_t port)
205{
206  #if defined(ArduinoProMini)
207    UCSR0B |= (1<<UDRIE0);
208  #endif
209  #if defined(ArduinoProMicro)
210    switch (port)
211    {
212      case 1: UCSR1B |= (1<<UDRIE1); break;
213    }
214  #endif
215  #if defined(ArduinoMega)
216    switch (port)
217    {
218      case 0: UCSR0B |= (1<<UDRIE0); break;
219      case 1: UCSR1B |= (1<<UDRIE1); break;
220      case 2: UCSR2B |= (1<<UDRIE2); break;
221      case 3: UCSR3B |= (1<<UDRIE3); break;
222    }
223  #endif
224}
225 
226/// <summary>
227// Сохраняем отправляемый байт в буфер TX для хранения данных и отправляем данные по UART, включаем прерывание по опустошению буффера UART
228/// </summary>
229/// <param name="port">Номер порта</param>
230/// <param name="c">Отправляемый байт</param>
231void UARTWrite(uint8_t port, uint8_t c)
232{
233  UARTSerialize(port,c);UARTSendData(port);
234}
235 
236/// <summary>
237// Получает количество байт доступных для чтения из буфера RX
238/// </summary>
239/// <param name="port">Номер порта</param>
240uint8_t UARTAvailable(uint8_t port)
241{
242  return ((uint8_t)(SerialHeadRX[port] - SerialTailRX[port]))%RXBufferSize;
243}
244 
245/// <summary>
246// Читаем данные из буфера RX для хранения данных
247/// </summary>
248/// <param name="port">Номер порта</param>
249uint8_t UARTRead(uint8_t port)
250{
251  // Получаем номер "хвоста масива" RX
252  uint8_t t = SerialTailRX[port];
253  // Получаем байт по номеру "хвоста масива" RX
254  uint8_t c = SerialBufferRX[t][port];
255   
256  // Проверяем номер "головы масива" RX и номер "хвоста масива" RX если не равен
257  if (SerialHeadRX[port] != t)
258  {
259     // Проверяем, увеличиваем номер "хвоста масива" RX хвоста на 1 и если номер "хвоста масива", станет равным или больше размера буфера, обнуляем переменную t в 0 
260    if (++t >= RXBufferSize)
261    {
262      t = 0;
263    }
264    // Сохраняем новый номер "хвоста масива" RX
265    SerialTailRX[port] = t;
266  }
267  return c;
268}
269 
270/// <summary>
271// Закрываем UART порт
272/// </summary>
273/// <param name="port">Номер порта</param>
274void UARTClose(uint8_t port)
275{
276  switch (port)
277  {
278    #if defined(ArduinoProMini)
279      case 0: UCSR0B &= ~((1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0)|(1<<UDRIE0)); break;
280    #endif
281    #if defined(ArduinoProMicro)
282      case 1: UCSR1B &= ~((1<<RXEN1)|(1<<TXEN1)|(1<<RXCIE1)|(1<<UDRIE1)); break;
283    #endif
284    #if defined(ArduinoMega)
285      case 0: UCSR0B &= ~((1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0)|(1<<UDRIE0)); break;
286      case 1: UCSR1B &= ~((1<<RXEN1)|(1<<TXEN1)|(1<<RXCIE1)|(1<<UDRIE1)); break;
287      case 2: UCSR2B &= ~((1<<RXEN2)|(1<<TXEN2)|(1<<RXCIE2)|(1<<UDRIE2)); break;
288      case 3: UCSR3B &= ~((1<<RXEN3)|(1<<TXEN3)|(1<<RXCIE3)|(1<<UDRIE3)); break;
289    #endif
290  }
291}

 UART.h
 

01#ifndef UART_H_
02#define UART_H_
03 
04/**************************************************************************************/
05/*****************             Класс работы с UART               **********************/
06/**************************************************************************************/
07 
08// Определяем кол-во UART-тов в зависимости от платы
09#if defined(ArduinoMega)
10  // Если ArduinoMega
11  #define UARTNumber 4
12#elif defined(ArduinoProMicro)
13  // Если ArduinoProMicro
14  #define UARTNumber 1
15#else
16  // Иначе предполагается ArduinoProMini
17  #define UARTNumber 1
18#endif
19 
20// Размер буфера RX
21#define RXBufferSize 128
22 
23// Размер буфера TX
24#define TXBufferSize 128
25 
26/// <summary>
27// Инициализируем и открываем UART порт
28/// </summary>
29/// <param name="port">Номер порта</param>
30/// <param name="baud">Скорость работы порта</param>
31void UARTOpen(uint8_t port, uint32_t baud);
32 
33/// <summary>
34// // Сохраняем отправляемый байт в буфер TX для хранения данных
35/// </summary>
36/// <param name="port">Номер порта</param>
37/// <param name="a">Отправляемый байт</param>
38void UARTSerialize(uint8_t port, uint8_t a);
39 
40/// <summary>
41// Отправляем данные по UART, включаем прерывание по опустошению буффера UART
42/// </summary>
43/// <param name="port">Номер порта</param>
44void UARTSendData(uint8_t port);
45 
46/// <summary>
47// Сохраняем отправляемый байт в буфер TX для хранения данных и отправляем данные по UART, включаем прерывание по опустошению буффера UART
48/// </summary>
49/// <param name="port">Номер порта</param>
50/// <param name="c">Отправляемый байт</param>
51void UARTWrite(uint8_t port, uint8_t c);
52 
53/// <summary>
54// Получает количество байт доступных для чтения из буфера RX
55/// </summary>
56/// <param name="port">Номер порта</param>
57uint8_t UARTAvailable(uint8_t port);
58 
59/// <summary>
60// Читаем данные из буфера RX для хранения данных
61/// </summary>
62/// <param name="port">Номер порта</param>
63uint8_t UARTRead(uint8_t port);
64 
65/// <summary>
66// Закрываем UART порт
67/// </summary>
68/// <param name="port">Номер порта</param>
69void UARTClose(uint8_t port);
70 
71#endif /* UART_H_ */

Config.h
 

01#ifndef CONFIG_H_
02#define CONFIG_H_
03 
04/**************************************************************************************/
05/********************             Класс настроек                ***********************/
06/**************************************************************************************/
07 
08/********************************  Настройки UART  ************************************/
09#define UARTPort              0                    // Порт UART
10#define UARTSpeed             115200UL             // Скорость порта UART
11/*******************************  /Настройки UART  ************************************/
12 
13/*******************************  Настройки Debug  ************************************/
14//#define IS_DEBUG_LOOP_SPEED                        // Включение проверки максимального времени прохождения loop
15/*******************************  /Настройки Debug  ***********************************/
16 
17#endif /* CONFIG_H_ */

Def.h

 

01#ifndef DEF_H_
02#define DEF_H_
03 
04/**************************************************************************************/
05/******************             Класс определений                **********************/
06/**************************************************************************************/
07 
08/*****************************  Определяем тип ардуины  *******************************/
09#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega2560__)
10     
11  #define F_CPU 16000000UL                             // Частота процессора
12 
13  // Определяем тип ардуины
14  #if defined(__AVR_ATmega328P__)
15    // Если ArduinoProMini
16    #define ArduinoProMini
17  #endif
18  #if defined(__AVR_ATmega32U4__)
19    // Если ArduinoProMicro
20    #define ArduinoProMicro
21  #endif
22  #if defined(__AVR_ATmega2560__)
23    // Если ArduinoMega
24    #define ArduinoMega
25  #endif
26#endif
27/****************************  /Определяем тип ардуины  *******************************/
28 
29#endif /* DEF_H_ */

Protocol.cpp

01/**********************************  Библиотеки  **************************************/
02#include "Arduino.h"
03 
04#include "Config.h"
05 
06#include "UART.h"
07/**********************************  /Библиотеки  *************************************/
08 
09/**************************************************************************************/
10/**************          Класс протокола передачи данных           ********************/
11/**************************************************************************************/
12 
13void Serialize8(uint8_t a)
14{
15  UARTSerialize(UARTPort,a);
16}
17 
18void Serialize16(int16_t a)
19{
20  Serialize8((a   ) & 0xFF);
21  Serialize8((a>>8) & 0xFF);
22}
23 
24void Serialize32(uint32_t a)
25{
26  Serialize8((a    ) & 0xFF);
27  Serialize8((a>> 8) & 0xFF);
28  Serialize8((a>>16) & 0xFF);
29  Serialize8((a>>24) & 0xFF);
30}

Protocol.h

 

01#ifndef PROTOCOL_H_
02#define PROTOCOL_H_
03 
04/**************************************************************************************/
05/**************          Класс протокола передачи данных           ********************/
06/**************************************************************************************/
07 
08void Serialize8(uint8_t a);
09 
10void Serialize16(int16_t a);
11 
12void Serialize32(uint32_t a);
13 
14#endif /* PROTOCOL_H_ */

.ino
 

01/**************************************************************************************/
02/********************             Основной файл               *************************/
03/**************************************************************************************/
04 
05/**********************************  Библиотеки  **************************************/
06#include "Arduino.h"
07 
08#include "Config.h"
09 
10#include "Def.h"
11 
12#include "UART.h"
13 
14#include "Protocol.h"
15/**********************************  /Библиотеки  *************************************/
16 
17/******************************** Основные функции ************************************/
18/// <summary>
19/// Настройка при запуске arduino
20/// </summary>
21void setup()
22{
23  UARTOpen(UARTPort, UARTSpeed);
24}
25 
26int i = 0;
27 
28/// <summary>
29/// Основной цикл
30/// </summary>
31void loop()
32
33  if (i == 0)
34  {
35    // Отправка данных
36    Serialize8('H');
37    Serialize8('e');
38    Serialize8('l');
39    Serialize8('l');
40    Serialize8('o');
41    Serialize8('!');
42    Serialize8('\n');
43    UARTSendData(UARTPort);
44    i = 1;
45  }
46   
47  if (UARTAvailable(UARTPort) > 0)
48  {
49    uint8_t c = UARTRead(UARTPort);
50     
51    Serialize8(c);
52    UARTSendData(UARTPort);
53  }
54}
55/******************************** /Основные функции ***********************************/

Удачи!

Artur1985
Offline
Зарегистрирован: 19.02.2013

Да чуть не забыл, у меня пока нет рабочего протокола, смотрите MultiWii, там пример протокола. Отправка и получение, вставленны лишь для проверки. 
 

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Спасибо!

Artur1985
Offline
Зарегистрирован: 19.02.2013

Не за что, тут все помогают друг другу по мере сил.

wenom86
Offline
Зарегистрирован: 04.11.2012

Здравствуйте Artur1985 и Gippopotam. Телеметрия у меня будет выводиться именно на MAX7456. Первоначальный код действительно не самый удачный, как я посмотрю. О нем, если нужно, можно благополучно забыть. 

Artur1985
Offline
Зарегистрирован: 19.02.2013

День добрый wenom86.

wenom86 пишет:

Телеметрия у меня будет выводиться именно на MAX7456.

Тоже пока остановился на этой микросхеме. Если Вы покупали модуль, не подскажите где?

Ни РФ, ни в Китае не нашел отдельного модуля, есть платы OSD, но они совмещены с контролером, а как к ним подключится еще тот вопрос.

Доставка из США пока для меня не доступна.

 

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014
Artur1985
Offline
Зарегистрирован: 19.02.2013

Gippopotam пишет:

А что с этими не так?

http://www.ebay.com/itm/170934217208?_trksid=p2059210.m2749.l2649&ssPage...

Не понял Вас, Max485 это модуль RS-485 TTL. Чтобы его купить не надо искать его в США, они есть и у нас. Сам использую такой же, но к OSD он не имеет отношения. 
 
Очень часто, команды передаются на Rov по RS-485, а телеметрия просто налаживается на видео сигнал с помощью MAX7456. Поэтому нет необходимости слать данные наверх, если у Вас нет доп. задач.
 
MAX7456 используется для OSD, есть готовая библиотека для Ардуино и т.д. Если интересно можете почитать в интернете
 
wenom86
Offline
Зарегистрирован: 04.11.2012

MAX7456 заказывал летом с алиэкспреса. за 2 штуки вместе вышло около 11 баксов. Но это только 2 голые микрушки (обвес там, как я посмотрел, копеечный, у нас в радиомагазине все докупил)

wenom86
Offline
Зарегистрирован: 04.11.2012

Artur1985. Можете скинуть мне свою электронку? или напишите мне на wenom86@mail.ru  Думаю нам есть о чем пообщаться.

Artur1985
Offline
Зарегистрирован: 19.02.2013

wenom86 пишет:

MAX7456 заказывал летом с алиэкспреса. за 2 штуки вместе вышло около 11 баксов. Но это только 2 голые микрушки (обвес там, как я посмотрел, копеечный, у нас в радиомагазине все докупил)


Понятно думал используете модуль.
Пока стараюсь найти модуль, но если не получится найти, придется делать так же.
 

wenom86 пишет:

Artur1985. Можете скинуть мне свою электронку? или напишите мне на wenom86@mail.ru  Думаю нам есть о чем пообщаться.


Разумеется, письмо отправил.

Probelzaelo
Offline
Зарегистрирован: 15.04.2011

wenom86 пишет:
Ищу исполнителя для написания программного кода передатчика и приемника команд управления (вперед, назад, вращение на месте, включение и выключение источников света, управление манипулятором и т.д.)  Передача данных будет происходить по RS485. Аппаратная часть передатчика и приемника изготовлены и работают.

Андрей, а чем тебя не устроила обычная система управления "штатная" для RC ? с многоканальным же передатчиком/приемником. тебе и нужно всего ничего, исключить ВЧ составляющую и подавать PPM напрямую (с тренерского разьема например) через физический интерфейс типа 485 или что то подобное прямо двумя проводами, на дешифратор-приемника, дальше все "родное". дешифраторов там же обсуждалось в нескольких местах.

Artur1985
Offline
Зарегистрирован: 19.02.2013
День добрый.
Код передачи данных сделал, пока в одну сторону (но обратно Вам не нужно).
 
Для Вашей задачи надо изменить, лишь один метод, у меня пока джойстик от PS2.
 
В дальнейшем планирую отправку в обратную сторону и заменой управления выходами - прямой доступ к регистрам порта, по уму не плохо бы сделать или воспользоваться библиотекой (думаю на этой недели, но загадывать не буду). 
 
Artur1985
Offline
Зарегистрирован: 19.02.2013

С wenom86 моя связь оборвалась, хотел сделать реализацию под его задачи (строители Rov, должны помогать друг другу, нас осталось мало:)), но так как точно не вижу задачи, не рискну делать.

Мой код передачи данных можно увидеть тут. Будут вопросы, буду стараться отвечать по мере сил.

Сейчас прервался в написании кода, конструирую винты, редуктора, подбираю моторы (пока не рискну делать сам). Да и на работе дел прибавилось.