Внешний МК и Ардуино общаются по Serial. Помогите ламеру.
- Войдите на сайт для отправки комментариев
Руки уже чешутся!! Хочу юзать. Подкину 500 рубликов на телефон тому кто поможет поскорей начать.
Задание такое:
1. Описать подробно circuit. Куда ТХ куда RX.... и т.д.
2. Написать код для ардуино в котором внешний МК сообщает иногда одну из трёх команд:
80h (128) - - - - - > на тебе первую команду
8fh (143) - - - - - > на тебе вторую команду
26h (38)- - - - - > на тебе третью команду
А ардуина отвечает :
в ответ на первую < - - - - - 02h (02)
в ответ на вторую< - - - - - 02h (02)
в ответ на трерью< - - - - - 0fh (15)
Я буду потом править код под свои нужды. Поэтому очень желательно что бы все было в десятичной системе ибо мне так привычней (я в шестнадцатеричной не секу не робот).
А команды в какой момент должны отсылаться? через определенные промежутки времени или по нажатию на кнопку? или еще как?
У вас макетка есть, что бы второй МК запустить?
> Описать подробно circuit. Куда ТХ куда RX.... и т.д.
ну так вы-бы хоть признались какой у вас MK. Ладно, предположим что Atmega8.
Тогда TX дуины -> PD0 (вторая нога) , RX -> PD1 (треться нога).
Для сообщающией. Так как вы не описали , что значит "иногда", предположим что она шлет команды по очереди каждую секунду
#define DELAY 1000 byte commands[]={128,143,38};// команды которые нужно послать #define COMMAND_COUNT sieof(commands)/sizeof(byte); byte currentCommandIndex=0; unsigned long nextReportTime=0; void setup(){ Serial.begin(9600); } void loop(){ if(nextReportTime<millis()){ // пришло время посылать следующую команду Serial.write(commands[currentCommandIndex]); nextReportTime=millis()+DELAY; // вычисляем врямя когда нужно будет послать следующую команду } if(Serial.available()){ // что-то пришло в ответ byte bt=Serial.read();// прочитали ответ // что-то делаем с ответом, тут пишите свою логику } }Для отвечающей
void setup(){ Serial.begin(9600); } void loop(){ if(Serial.available()){ // пришла комманда byte bt=Serial.read();// прочитали ответ byte answer=0; // тут будет ответ switch(bt){ case 128: case 133: answer=02; break; case 38: answer=15; break; default: answer=0; //нет ответа, команда не известна } if(answer){ // если ответ имеется Serial.write(answer);// послыаем его } } }И не забываем про землю так как если источники питания разные то связи не будет.
Упс.... в отсылающей, забыл переход на следующую команду сделать.
Вот так правильней:
#define DELAY 1000 byte commands[]={128,143,38};// команды которые нужно послать #define COMMAND_COUNT sizeof(commands)/sizeof(byte) byte currentCommandIndex=0; unsigned long nextReportTime=0; void setup(){ Serial.begin(9600); } void loop(){ if(nextReportTime<millis()){ // пришло время посылать следующую команду Serial.write(commands[currentCommandIndex]); nextReportTime=millis()+DELAY; // вычисляем врямя когда нужно будет послать следующую команду currentCommandIndex++; // передвигаем индекс команд на следющий if(currentCommandIndex>=COMMAND_COUNT)currentCommandIndex=0;// и опять все с первой начинаем } if(Serial.available()){ // что-то пришло в ответ byte bt=Serial.read();// прочитали ответ // что-то делаем с ответом, тут пишите свою логику } }Внешний МК внутри корпуса я туда не лазил. имеет культурные выходы обозначенные как RX, TX, G. Команды шлет произвольно перерабатывая инфу от своих внешних датчиков .
отсылающей стороны код мне не нужен. это готовое устройство от поставщика и я его не кодирую. когда придет команда практически от нее не известно. известны лишь варианты ожидаемых команд. Пожалуйста поправьте все если нужно с учетом последнего замечания. и с декларацией переменных хотелось бы переменную в которой лежит принятая команда (может туплю, но что то я не вижу где переменные обявлялись) и сообщите мне свой мобильный номер и Вашего оператора, для перевода денег. А и совсем забыл я использую ардуину программирую в стандартном приложении от разработчиков Ардуины. В средствах разработки где используется чистый С я ни чего не понимаю (не знаю даже критично ли последее замечание)
byte bt=Serial.read() // не могу поверить. неужели в одной строчке идет обявление переменной и тут же присвоение значения????
может вынести об явление переменной до void setup(). Там обычно идут всякие int...
сорри за чайниковские вопросы..... развейте сомнения.
> не могу поверить.
А зачем верить? Можно же в ардуиноIDE вставить и убедится что компилятор не ругается.
Да и что в этом такого "удивительного"? Нелогиченого же ничего нет. Зачем писать две строки, где можно одну?
>может вынести об явление переменной до void setup(). Там обычно идут всякие int...
Если так спокойней - можно. Ничего страшного не случится.
Так как в ардуино скетчи относительно небольшого размера (десятки-сотни строк) - многие так и делают. А вот если "программа большая", то глобальные переменны (это те самые обычно идут всякие int...) - становятся злом. Если функций, всяких - сотни. То уже уследить что-бы две разные функции не начали использовать переменную по разному и не "мешали друг-другу" - уже сложней.
В одной функции counter - означает счетчик диодов, в другой - счетчик кнопок. Есть вероятность "не уследить" :(
Вообщем, "хороший стиль" - использовать глобальные переменные только когда "без них никак" (или нучно срочно какой-то костыль влепить).
Но еще раз - в ардуино-скетчах придерживаться этого "фен-шуя" не критично. Из-за их малого объема, "конфликт переменных" как правило виден простым взглядом.
окей. Спасибо, leshak. Хорошая работа. жду номер Вашего телефона. mig23@list.ru
отсылающей стороны код мне не нужен. это готовое устройство от поставщика и я его не кодирую. когда придет команда практически от нее не известно. известны лишь варианты ожидаемых команд. Пожалуйста поправьте все если нужно с учетом последнего замечания.
Ну не нужен, так не нужен. Что поправлять-то? Не берите его, да и все. Считайте что я его не писал :)
А и совсем забыл я использую ардуину программирую в стандартном приложении от разработчиков Ардуины. В средствах разработки где используется чистый С я ни чего не понимаю (не знаю даже критично ли последее замечание)
Совершенно не критично. Наоборот. Так как это ардуино форум, то если не оговоренно другое подразумевается что вы используете именно ArduinoIDE от разработчиков.
и сообщите мне свой мобильный номер и Вашего оператора, для перевода денег
Не, ну на форуме светить такое я точно не буду. Если хотите напишите на alxarduino[ЗАКРУЧЕННОЕ_УХО]gmail.com
Укажите ваш формуный ник, что-бы я понял о чем речь идет. В идеале - можете сразу дать скайп - свяжемся, обсудим. Может еще какие-то вопросы у вас возникнут. Но это не обязательно. Вообщем-то ответы на форуме бесплатны. Так что деньги - сугубо по вашей доброй воле ;)
Да и раз вы не управляете передающем устройством, вам нужно, еще выяснить на какой скорости оно передает и подправить строчку Serial.begin(9600); на правильную скорость.
Если список команд будете расширять, то можно сделать чуть по другому, что-бы не выписывать портянку свича, сделать через массивы
struct KeyValuePair{ // структура для описания пар запрос-ответ byte request; // запрос byte response;// ответ }; KeyValuePair rrPairs[]={ // массив хранящий на какие команды что нужно отвечать {128,02}, {143,02}, {38,15} // {0x26,0x0F} - то же самое что и предыдущая строчка, только в шестнадцатеричном виде. как видите - ничего страшного. просто "магические цифры". // вообщем тут можно еще добавить всяких разных комманд }; // вычисляем сколько у нас всего комманд #define TOTAL_PAIRS sizeof(rrPairs)/sizeof(KeyValuePair) byte bt; // OK. Для спокойствия вынесем его сюда void setup(){ Serial.begin(9600); } void loop(){ if(Serial.available()){ // что-то пришло bt=Serial.read();// читаем пришедшие for(int i=0;i<TOTAL_PAIRS;i++){ // пробегаемся по всем командам ищем подходящуюю if(bt==rrPairs[i].request){ // о, подходит Serial.write(rrPairs[i].response);// отвечаем break;// дальше по циклу идти смысла нет, так как команда может иметь только один ответ } } } }Тогда для добавления еще одной команды, будет достаточно вписать ее в массив rrPairs
Внешний МК внутри корпуса я туда не лазил. имеет культурные выходы обозначенные как RX, TX, G. Команды шлет произвольно перерабатывая инфу от своих внешних датчиков .
Э.... на всяк случай. Проверте вольтметром что там у вас на пинах. Что-бы случайно не оказалось что это RX,TX какого-нибудь RS232 12-ти вольтового. Тогда нужно еще уровни согласовать, что-бы входы дуины не выпалить.
Или, наоборот. Там входы 3-х вольтовые, а вы вкатите туда дуиной 5v. Тоже может быть череповато.
НИ когда не замерял раньше цифру. Между чем и чем замерять? А что ждать от вольтметра? Если выходы 5в за счет добавления битов патенциалом 0в показания усредняться до 2.5в. А если выводы 3х вольтовые то вообще 1.5в покажет?
Замер всегда делается между "точкой замера" и "землей". В вашем случае - между пином и "общей землей".
> усредняться до 2.5в
Ну если, в этот момент нули и единицы будут идти примерно в равном количестве. Если там 1 будет пробегать "раз в пятилетку", то вы будите видить ноль. И "ловить" там уже нужно будет не тестером, а в осцилографом.
Вообще, в идеале, это нужно не мерять, а смотреть в документации на устройство. Или "сцепить зубы и рискнуть" ;)
Если выход 3-х вольтовый, то ардуина должна прочитать его "напрямую", без доп. обвязки.
А вот если "вход" трех вольтовый, то тут уже возможны два варианта (но узнать можно только из доков).
1. На этот вход нельзя подавать больше 3-х вольт. Тогда читаем статью http://we.easyelectronics.ru/Shematech/soglasovanie-logicheskih-urovney-5v-i-33v-ustroystv.html Лично мне нарвится вариант "диодный интерфейс". Хорошее, как на меня, соотношение простоты и безопастности.
2. Некоторые 3-х вольтовые чипы, хоть и имеют 3-х вольтовые входы, но могут без ущерба для себя переваривать и 5v на входе. Тогда у них в даташите пишется что-то типа "TTL tolerance", "5v tolerant" и т.п. В этом случае опять,таки "можно подключать на прямую". Если такого не сказанно - смотрим предыдущий пункт.
А можно еще саму ардуину заюзать в качестве вольтметра.
Что-бы отличить 5v выход, от 3v вход-а.
Заливаем такой скетч:
unsigned long nextReportTime=0; int maxAnalogValue=0; void setup(){ Serial.begin(9600); } void loop(){ int currentAnalogValue=analogRead(A0); // читаем напряжение на аналоговом пине if(currentAnalogValue>maxAnalogValue)maxAnalogValue=currentAnalogValue;// запомнили новое максимальное значение // Выводим максимальное значение раз в секунда if(nextReportTime<millis()){ Serial.print("Max V="); Serial.println(map(maxAnalogValue,0,1023,0,5),DEC); // вывели пересчитат в вольты nextReportTime=millis()+1000;// вычислили когда нужно будет сделать следующий отчет } }Подключаем TX, устройства на Analog0 пин дуины, открываем в Serial Monitor в ArduinoIDE. Ждем пока устройство "что-нибудь пошлет". В мониторе, раз в секуду, увидим какое максимальное напряжения было на аналоговом входе. 5v или 3v.
Таким же макаром можно и 12v проверить. Только подключить его не напрямую, а через делить напряжения, который понизит 12v до 5v.
Если скетч будет репортить максимальное напряжение 5v - значит выход устройства - 12v-вольтовый, если меньше, то скорее всего 5v или 3v (смотря на сколько меньше).
Спасибо. Очень исчерпывающе. Я бы даже сказал христоматийно!