Написание кода передатчика и приемника (для подводного аппарата) за вознаграждение
- Войдите на сайт для отправки комментариев
Здравствуйте. У меня в разработке проект подводного телеуправляемого аппарата. Не коммерция, чисто хобби. Посмотреть о чем речь можно в этой теме: 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 |
017 | int LeftStickX = 0; // переменная Левого стика - ось X (вниз-вверх) |
018 | int LeftStickY = 1; // переменная Левого стика - ось Y (пока неиспользуется) |
019 | int RightStickX = 2; // переменная Правого стика - ось X (вперед-назад) |
020 | int RightStickY = 3; // переменная Правого стика - ось Y (влево-вправо) |
021 |
022 | int Pin2 = 2; //пин 2 используется для включения передачи данных по rs485 |
023 | int Knopka1 = 10; //кнопка1 подключена к 3 цифровому контакту (освещение 1) (фиксируемая) |
024 | int Knopka2 = 7; //кнопка2 подключена к 4 цифровому контакту (освещение 2) (фиксируемая) |
025 | int Knopka3 = 8; //кнопка3 подключена к 5 цифровому контакту (освещение 3) (фиксируемая) |
026 | int Knopka4 = 6; //кнопка4 подключена к 6 цифровому контакту (освещение 4) (фиксируемая) |
027 | int Knopka7 = 11; //кнопка7 подключена к 7 цифровому контакту (манипулятор - сжать) (нефиксируемая) |
028 | int Knopka8 = 5; //кнопка8 подключена к 8 цифровому контакту (манипулятор - разжать) (нефиксируемая) |
029 | int Knopka9 = 4; //кнопка9 подключена к 9 цифровому контакту (камера - вверх) |
030 | int Knopka10 = 3; //кнопка10 подключена к 10 цифровому контакту (камера - вниз) |
031 | int Knopka11 = 9; //кнопка11 подключена к 11 цифровому контакту (резервная) (нефиксируемая) |
032 | int MotorPin = 12; //моторы в пульте управления подключены через транзистор к 12 цифровому контакту (пока никак не используются) |
033 | //int LedPin = 13; // инициализация светодиода, светодиод в пульте управления подключен к 13 цифровому контакту |
034 | int KanalMotoraLevogoGor, KanalMotoraPravogoGor, KanalMotoraPerVert, KanalMotoraZadVert; |
035 | int PinUpr1 = 13; |
036 | int flag1, flag2, flag3, flag4 = 0; |
037 | int KanalKn1, KanalKn2, KanalKn3, KanalKn4 = 0; |
038 |
039 | void 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 |
066 | void 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 | } |
Добрый день!
Не совсем понятно задание. Из описания - все просто (даже элементарно), тем более у вас есть программа. В чем подвох?
Дело в том, что катастрофически не хватает времени на изучение программирования. И так хотел запустить аппарат летом 2014, но загвоздка в программе была, хотел сам изучить, но дальше азов не продвинулся. Программа может пока легкая, только будет обрастать доп. Функциями. Подвоха нет, просто нужна помощь человеку-железячнику в программировании.
При нажатии на ссылку она не открывается. Чтобы открыть, необходимо стереть в конце ссылки 1 пробел.
Добрый вечер.
Искал ответ по синхронизации передачи данных по RS485 и случайно увидел Ваше сообщение. Сам сейчас с другом делаем наброски по аналогичному проекту - проект подводного телеуправляемого аппарата. Приятно видеть, что не только нам лавры Кусто не дают уснуть:).
Тоже делаю на RS485 передачу управления, делаю в свободное время.
По коду
Имеется код, который был написан ранее (если он подходит - отталкиваться необходимо от него)
Не рекомендовал бы использовать данный код в готовом решении.
Начнем с UART (Serial), лучше делать отправку и получение на прерываниях + передача байтами + кольцевой буфер, это уменьшит размер кода и сделает его более эффективным, без лишних задержек.
Более рациональное использование ресурсов позволит в будущем иметь запас по расширению, к примеру, для стабилизации при течении (акселерометр, гироскоп) и т.д. Тем более
Примерное описание, данной реализации с неплохим пояснением.
Крайне не желательно использовать delay в loop.
Вы являетесь заказчиком, рекомендовал бы изменить требования к коду для разработчика.
Проект как я понял, почти закончен. Но возможно, будет полезно использование Playstation joystick, вместо кнопок. Более подробно тут.
Будут вопросы, пишите.
Artur1985, а с вашими набросками можно познакомиться?
Отчасти, увы нет времени их публиковать. Сейчас проходят тесты отдельные модули, работы еще много, в том числе и кодинга.
Я пишу коды и разбераюсь с электроникой, мой друг механикой и корпусом.
Вот пару фото

Габариты 164*156*202мм.
Меня, как волонтера, именно кодовая часть интересует.
Тут все очень сильно зависит от конкретного Rov. К примеру, для классического Rov, данные идут с береговой станции на Rov, а телеметрия отображается на видео сигнале. К примеру на той же MAX7456.
Я не стал изобретать велосипед и воспользовался проектом Multiwii, там хорошая схема передачи данных, простой протокол + проверенный IMU. Сейчас подпиливаю под собственные нужды протокол и думаю над синхронизации RS-485. У меня не классический Rov, данные идут в обе стороны.
Меня, как волонтера, именно кодовая часть интересует.
Готового решения у меня пока нет, делается в свободное время.
Мое решение, без доработки использовать не получится. Да можно будет взять саму передачу данных, но протокол придется переписывать. Так как он будет заточен, под особенности моего Rov.
Добрался до рабочего компа, как я говорил, лучше если Вы посмотрите код оригинала.
Вот мой код, по сути код от 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 для хранения "хвоста масива"
017
static
volatile uint8_t SerialHeadRX[UARTNumber],SerialTailRX[UARTNumber];
018
019
// SerialBufferRX - буфер RX для хранения данных
020
static
uint8_t SerialBufferRX[RXBufferSize][UARTNumber];
021
022
// SerialHeadTX - буфер TX для хранения "головы масива"
023
// SerialTailTX - буфер TX для хранения "хвоста масива"
024
static
volatile uint8_t SerialHeadTX[UARTNumber],SerialTailTX[UARTNumber];
025
026
// SerialBufferTX - буфер X для хранения данных
027
static
uint8_t SerialBufferTX[TXBufferSize][UARTNumber];
028
029
/// <summary>
030
// Инициализируем и открываем UART порт
031
/// </summary>
032
/// <param name="port">Номер порта</param>
033
/// <param name="baud">Скорость работы порта</param>
034
void
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>
066
void
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>
189
void
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>
204
void
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>
231
void
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>
240
uint8_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>
249
uint8_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>
274
void
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>
31
void
UARTOpen(uint8_t port, uint32_t baud);
32
33
/// <summary>
34
// // Сохраняем отправляемый байт в буфер TX для хранения данных
35
/// </summary>
36
/// <param name="port">Номер порта</param>
37
/// <param name="a">Отправляемый байт</param>
38
void
UARTSerialize(uint8_t port, uint8_t a);
39
40
/// <summary>
41
// Отправляем данные по UART, включаем прерывание по опустошению буффера UART
42
/// </summary>
43
/// <param name="port">Номер порта</param>
44
void
UARTSendData(uint8_t port);
45
46
/// <summary>
47
// Сохраняем отправляемый байт в буфер TX для хранения данных и отправляем данные по UART, включаем прерывание по опустошению буффера UART
48
/// </summary>
49
/// <param name="port">Номер порта</param>
50
/// <param name="c">Отправляемый байт</param>
51
void
UARTWrite(uint8_t port, uint8_t c);
52
53
/// <summary>
54
// Получает количество байт доступных для чтения из буфера RX
55
/// </summary>
56
/// <param name="port">Номер порта</param>
57
uint8_t UARTAvailable(uint8_t port);
58
59
/// <summary>
60
// Читаем данные из буфера RX для хранения данных
61
/// </summary>
62
/// <param name="port">Номер порта</param>
63
uint8_t UARTRead(uint8_t port);
64
65
/// <summary>
66
// Закрываем UART порт
67
/// </summary>
68
/// <param name="port">Номер порта</param>
69
void
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
13
void
Serialize8(uint8_t a)
14
{
15
UARTSerialize(UARTPort,a);
16
}
17
18
void
Serialize16(int16_t a)
19
{
20
Serialize8((a ) & 0xFF);
21
Serialize8((a>>8) & 0xFF);
22
}
23
24
void
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
08
void
Serialize8(uint8_t a);
09
10
void
Serialize16(int16_t a);
11
12
void
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>
21
void
setup
()
22
{
23
UARTOpen(UARTPort, UARTSpeed);
24
}
25
26
int
i = 0;
27
28
/// <summary>
29
/// Основной цикл
30
/// </summary>
31
void
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
/******************************** /Основные функции ***********************************/
Удачи!
Да чуть не забыл, у меня пока нет рабочего протокола, смотрите MultiWii, там пример протокола. Отправка и получение, вставленны лишь для проверки.
Спасибо!
Не за что, тут все помогают друг другу по мере сил.
Здравствуйте Artur1985 и Gippopotam. Телеметрия у меня будет выводиться именно на MAX7456. Первоначальный код действительно не самый удачный, как я посмотрю. О нем, если нужно, можно благополучно забыть.
День добрый wenom86.
Телеметрия у меня будет выводиться именно на MAX7456.
Тоже пока остановился на этой микросхеме. Если Вы покупали модуль, не подскажите где?
Ни РФ, ни в Китае не нашел отдельного модуля, есть платы OSD, но они совмещены с контролером, а как к ним подключится еще тот вопрос.
Доставка из США пока для меня не доступна.
А что с этими не так?
http://www.ebay.com/itm/170934217208?_trksid=p2059210.m2749.l2649&ssPage...
А что с этими не так?
http://www.ebay.com/itm/170934217208?_trksid=p2059210.m2749.l2649&ssPage...
MAX7456 заказывал летом с алиэкспреса. за 2 штуки вместе вышло около 11 баксов. Но это только 2 голые микрушки (обвес там, как я посмотрел, копеечный, у нас в радиомагазине все докупил)
Artur1985. Можете скинуть мне свою электронку? или напишите мне на wenom86@mail.ru Думаю нам есть о чем пообщаться.
MAX7456 заказывал летом с алиэкспреса. за 2 штуки вместе вышло около 11 баксов. Но это только 2 голые микрушки (обвес там, как я посмотрел, копеечный, у нас в радиомагазине все докупил)
Понятно думал используете модуль.
Пока стараюсь найти модуль, но если не получится найти, придется делать так же.
Artur1985. Можете скинуть мне свою электронку? или напишите мне на wenom86@mail.ru Думаю нам есть о чем пообщаться.
Разумеется, письмо отправил.
Андрей, а чем тебя не устроила обычная система управления "штатная" для RC ? с многоканальным же передатчиком/приемником. тебе и нужно всего ничего, исключить ВЧ составляющую и подавать PPM напрямую (с тренерского разьема например) через физический интерфейс типа 485 или что то подобное прямо двумя проводами, на дешифратор-приемника, дальше все "родное". дешифраторов там же обсуждалось в нескольких местах.
С wenom86 моя связь оборвалась, хотел сделать реализацию под его задачи (строители Rov, должны помогать друг другу, нас осталось мало:)), но так как точно не вижу задачи, не рискну делать.
Мой код передачи данных можно увидеть тут. Будут вопросы, буду стараться отвечать по мере сил.
Сейчас прервался в написании кода, конструирую винты, редуктора, подбираю моторы (пока не рискну делать сам). Да и на работе дел прибавилось.