Технический форум по робототехнике.
falanger » 07 ноя 2016, 00:13
Опять появилось время на Ардуино и расскажу ободной "но" с которым я столкнулся пользуясь платой Adruino Uno с Arduino Sensor Shield 5.0.
А конкретно - после подключения 2-х моторов через Н-мосты (4 пина), 2-ж энкодеров (2 пина), 2-х оптодатчиков (2 пина), 2-х ИК-баимперов (2 пина) и одного ультразвукового дальномерчика (2 пина) - оказалось что не осталось свободных пинов!
Т.е. для чего-то "относительно богатого сенсорами" плата оказалась "мала", надо сразу замахиваться на 1280 или 2560 плату где много пинов, или разбивать работу по паре мелких плат и как-то их синхронизировать по UART.
metric » 07 ноя 2016, 02:31
Madf » 07 ноя 2016, 11:46
Эта штука не умеет одновременно/синхронно организовывать обмен по всем каналам. Это "аля" обычный комутатор. Обмен будет с задержками, даже если организовывать вывод по 1 байту (на время скорости передачи).
Вообще использовать UART для расширения - плохой вариант, лучше
такое для управления всячиной. Так же для разгрузги ног слабых дунь, использовать готовые контрллеры (например: для управления моторами).
metric » 07 ноя 2016, 17:52
это смотря какая скорость нужна, тут она делится пропорционально колличеству подключенных по uart. те если нужно 4-5 доп канала по 38k, то задержек не будет.
Madf » 07 ноя 2016, 19:40
с чего это их не будет?
S1-S3 - это как раз "селектор" канала вывода
в робототехники как правило нужно всем управлять, одновременно
есть у меня
робот о 17 сервах, управлялись они как раз все одновременно по UART, там нужно было 5 каналов одновременно данные слать, вот штукой выше - фиг нормально управляться будет
я ваще слабо представляю где её можно использовать, ибо у неё даже прерывания о событии извне нет, входящие данные будут просто пропадать (а вот в PCF8575 - есть)...за такие деньги можно кучу комплектухи прикупить
metric » 07 ноя 2016, 21:38
Madf писал(а):с чего это их не будет?
S1-S3 - это как раз "селектор" канала вывода
в робототехники как правило нужно всем управлять, одновременно
одновременно в данном случае = не слишком большая задержка, не более. реальный realtime никто не использует, и редко кто делает что бы каждый канал отдельно управлялся своим потоком что бы минимизировать задержки. этого просто не требуется, те скорость на уровне 8/115200=0.000069 сек на команду более чем достаточно
Madf писал(а):у неё даже прерывания о событии извне нет, входящие данные будут просто пропадать (а вот в PCF8575 - есть)
с чего это они пропадать должны? PCF8575 это i2c, может не будем мешать красное с горячим?
Madf » 07 ноя 2016, 23:15
Причем здесь "красное с горячим", речь идет о расширениях, их тьма!
А данные будут пропадать, если скажем подключить GSM-модем и БТ-модуль - никто из них не будет ждать, когда вы будите переключать свои каналы.)
Myp » 07 ноя 2016, 23:41
микроконтроллер может обмениваться данными либо с блютусом, либо с модемом, независимо от количества свободных у него ножек.
дело тут не в переключении каналов или количество ног процессора. данные будут пропадать при любом раскладе, поэтому надо заранее озаботиться о разделении по времени.
Madf » 08 ноя 2016, 11:37
Myp писал(а):данные будут пропадать при любом раскладе, поэтому надо заранее озаботиться о разделении по времени.
Да, только жесткий мастер/слейв.
falanger » 11 апр 2017, 17:23
Начал опять заниматься контроллером и конкретно этим шасси. Учусь программировать Ардуино, решив сделать WiFi-бота. Благо есть очень удачный мелкий роутер TP-LINK TL-MR3020 с ОпенРоботикс прошивкой, к которому еще нетрудно подключить внешнюю антенну и поднять дальность вайфая почти в два раза.
Пока же научился читать состояния датчиков и опять уперся в недостаточное количество ног Arduino Uno.
"На уровне шасси" ведь надо иметь:
2 датчика "пола" - 2 пина.
2 датчика "света" - 2 пина.
Ультразвуковой дальномер - 2 пина.
Драйвер L298N с ШИМ-регулировкой скорости и энкодерами - 4 х 2 = 8 пинов.
Итого уже 14 пинов. А ведь еще надо:
UART от роутера - 2 пина.
Серва на камеру - 1 пин.
Телеметрия напряжения батареи - 1 пин.
И даже если отказаться от датчиков освещенности - все равно "по хорошему" пинов не хватает на все хотелки.
Пока же скетч мой тестовый вот такой, части относящиеся к дальномеру закомментированы.
- Код: Выделить всё • Развернуть
/* Программа робота Tестовая версия 0.0.1 для Arduino Uno */
// Назначаем входы-выходы Arduino как переменные вида xxxPin
// int Trig_Pin = ; // Вход Trig ультразвукового дальномера, на который контроллер подает сигнал для посылки иипульса измерения
// int Echo_Pin = ; // Выход Echo ультразвукового дальномера, с которого контроллер получает сигнал импульса измерения
int Bamp1_Pin = 6 ; // Выход датчика "пола" номер 1, с которого контроллер получает сиогнал есть/нет пол
int Bamp2_Pin = 7 ; // Выход датчика "пола" номер 2, с которого контроллер получает сиогнал есть/нет пол
int Opt1_Pin = 8 ; // Выход датчика "света" номер 1, с которого контроллер получает сиогнал есть/нет свет на датчике
int Opt2_Pin = 9 ; // Выход датчика "света" номер 2, с которого контроллер получает сиогнал есть/нет свет на датчике
// int RxD_Pin = ; // Вход UART контроллера
// int TxD_Pin = ; // Выход UART контроллера
int Left1_Pin = 5 ; // Выход "Вперед" на драйвер двигателя левого борта
int Left2_Pin = 4 ; // Выход "Назад" на драйвер двигателя левого борта
int LeftPWR_Pin = 3 ; // Выход ШИМ "Скорость" на драйвер двигателя левого борта
int LeftSpeed_Pin = 2 ; // Вход "Скорость" энкодера двигателя левого борта
int Rignt1_Pin = 13 ; // Выход "Вперед" на драйвер двигателя правого борта
int Rignt2_Pin = 12 ; // Выход "Назад" на драйвер двигателя правого борта
int RigntPWR_Pin = 11 ; // Выход ШИМ "Скорость" на драйвер двигателя правого борта
int RigntSpeed_Pin = 10 ; // Вход "Скорость" энкодера двигателя правого борта
// Назначение переменных содержащих состояния датчиков
// unsigned int impulseTime=0; // Переменная содержащая значение времени импульса с дальномера
// unsigned int distance_sm=0; // Переменная содержащая значение дистанции с дальномера в сантиметрах
int valueBamp1 ; // Состояние датчика "пола" номер 1
int valueBamp2 ; // Состояние датчика "пола" номер 2
int valueOpt1 ; // Состояние датчика "света" номер 1
int valueOpt2 ; // Состояние датчика "света" номер 2
// Конфигурирование портов ввода-вывода Arduino и инициализация переменных, исполняется один раз при запуске
void setup()
{
Serial.begin(9600); // Конфигурирование последовательного порта на скорость 9600 бод
// pinMode(Trig_Pin, OUTPUT); // Конфигурирование порта как выход для посылки импульса дальномера
// pinMode(Echo_Pin, INPUT); // Конфмгурация порта как вход для приема импульса дальномера
pinMode(Bamp1_Pin, INPUT); // Конфигурация порта как вход для приема сигнала датчика "пола" номер 1
pinMode(Bamp2_Pin, INPUT); // Конфигурация порта как вход для приема сигнала датчика "пола" номер 2
pinMode(Opt1_Pin, INPUT); // Конфигурация порта как вход для приема сигнала датчика "света" номер 1
pinMode(Opt2_Pin, INPUT); // Конфигурация порта как вход для приема сигнала датчика "света" номер 2
pinMode(Left1_Pin, OUTPUT); // Конфигурация порта на выход "Вперед" на драйвер двигателя левого борта
pinMode(Left2_Pin, OUTPUT); // Конфигурация порта на выход "Назад" на драйвер двигателя левого борта
pinMode(LeftPWR_Pin, OUTPUT); // Конфигурация порта на выход ШИМ "Скорость" на драйвер двигателя левого борта
pinMode(LeftSpeed_Pin, INPUT); // Конфигурацмя порта на вход "Скорость" энкодера двигателя левого борта
pinMode(Rignt1_Pin, OUTPUT); // Конфигурация порта на выход "Вперед" на драйвер двигателя правого борта
pinMode(Rignt2_Pin, OUTPUT); // Конфигурация порта на выход "Назад" на драйвер двигателя правого борта
pinMode(RigntPWR_Pin, OUTPUT); // Конфигурация порта на выход ШИМ "Скорость" на драйвер двигателя правого борта
pinMode(RigntSpeed_Pin, INPUT); // Конфигурация порта на вход "Скорость" энкодера двигателя правого борта
}
// Основная программа Arduino, исполняется как бесконечный цикл
void loop()
{
// digitalWrite(Trig_Pin, HIGH); // Подаем импульс на вход Trig дальномера
// delayMicroseconds(10); // равный 10 микросекундам
// digitalWrite(Trig_Pin, LOW); // Отключаем
// impulseTime=pulseIn(Echo_Pin, HIGH); // Замеряем длину импульса
// distance_sm=impulseTime/58; // Пересчитываем в сантиметры
// Serial.print("Distance sm = "); // Вывод значения расстояния с ультразвукового дальномера в последовательный порт
// Serial.println(distance_sm); // Выводим на порт
// delay(100); // ждем 0.1 секунды, Следующий импульс может быть излучён, только после исчезновения эха от предыдущего.
// Это время называется периодом цикла (cycle period). Рекомендованный период между импульсами должен быть не менее 50 мс.
int valueBamp1 = digitalRead(Bamp1_Pin); // Считывается состояние датчика "пола" номер 1 и запись его в переменную
int valueBamp2 = digitalRead(Bamp2_Pin); // Считывается состояние датчика "пола" номер 2 и запись его в переменную
int valueOpt1 = digitalRead(Opt1_Pin); // Считывается состояние датчика "света" номер 1 и запись его в переменную
int valueOpt2 = digitalRead(Opt2_Pin); // Считывается состояние датчика "света" номер 2 и запись его в переменную
Serial.print("Bamp1 = "); // Вывод значения состояния датчика "пола" номер 1 в последовательный порт
Serial.println(valueBamp1); // Считыывние переменной со значением датчика "пола" номер 1 для вывода в последовательный порт
Serial.print("Bamp2 = "); // Вывод значения состояния датчика "пола" номер 2 в последовательный порт
Serial.println(valueBamp2); // Считыывние переменной со значением датчика "пола" номер 2 для вывода в последовательный порт
delay(500); // Ждем пол секунды
Serial.print("Opt1 = "); // Вывод значения состояния датчика "света" номер 1 в последовательный порт
Serial.println(valueOpt1); // Считыывние переменной со значением датчика "света" номер 1 для вывода в последовательный порт
Serial.print("Opt2 = "); // Вывод значения состояния датчика "света" номер 2 в последовательный порт
Serial.println(valueOpt2); // Считыывние переменной со значением датчика "света" номер 2 для вывода в последовательный порт
delay(500); // Ждем пол секунды
}
Текст программы обильно откомментирован и пока в нем только установка и обработка датчиков, да назначение выходов на драйверы. За управление моторами и логику обработки датчиков даже еще и не брался...
Последний раз редактировалось
falanger 11 апр 2017, 22:14, всего редактировалось 1 раз.
SkyStorm » 11 апр 2017, 19:18
для кода есть специальные теги.
falanger » 11 апр 2017, 22:22
Еще немного поигрался с кодом, нашел пример со считыванием кнопки и приспособил для считывания энкодеров китайских с шасси. Но там просто счетчики вышли, а надо обрабатывать именно как число импульсов за 1 секунду.
Может кто подскажет?
- Код: Выделить всё • Развернуть
int LeftSpeed_Pin = 10 ; // Вход "Скорость" энкодера двигателя левого борта
int LeftSpeedPushCounter = 0; // счетчик для количества импульсов левого энкодера
int LeftSpeedState = 0; // текущее состояние выхода левого энкодера
int lastLeftSpeedState = 0; // предыдущее состояние выхода левого энкодера
void setup()
{
Serial.begin(9600); // Конфигурирование последовательного порта на скорость 9600 бод
pinMode(LeftSpeed_Pin, INPUT); // Конфигурация порта на вход "Скорость" энкодера двигателя левого борта
}
void loop()
{
LeftSpeedState = digitalRead(LeftSpeed_Pin); // считываем данные с выхода левого энкодера
if (LeftSpeedState != lastLeftSpeedState) // сравниваем текущее состояние выхода энкодера с предыдущим:
{
if (LeftSpeedState == HIGH)
{
LeftSpeedPushCounter++; // если состояние изменилось, увеличиваем значение счетчика
Serial.print("Impulse left speed: ");
Serial.println(LeftSpeedPushCounter);
}
lastLeftSpeedState = LeftSpeedState; // для прогона через следующий цикл делаем текущее состояние предыдущим
}
}
RootAdmin » 11 апр 2017, 22:32
Импульсы за секунду считать -негодно. Надо измерять период между импульсами.
falanger » 11 апр 2017, 23:24
Кусок кода как пример?
На этом шасси энкодер дубовый - диск с четырьмя секторами вырезанными на валу мотора и все. Еще оптопара и все считай.
falanger » 16 апр 2017, 02:42
Разбираюсь с этим шасси дальше, пока читать энкодеры его так и не научился и даже не задавался, встал вопрос компоервкм оборудования.
И выяснилось что шасси достаточно дурацкое. дырки на хрупком пластике "верхней части" не совпадают с ардуиной и и ее датчиками чуть больше чем никак, дна дырка только совпадает с сервой маленькой на 9 грамм.
При этом ели например городить на машину батарею литиевую авиамодельную на 3 ячейки - ардуина и сенсоры не говоря уже о роутере с камерой оказываются задраны просто неприлично высоко.
Придется навинчивать стойки, закреплять на "первой палубе" часть оборудования и громоздить второй этаж. А батарею я загнал "под днище. там над шпильками связывающими вместе борта шасси гусеничного для нее нашлось место, если притянуть ее к шпилькам стяжками пластиковыми.