Внешний МК и Ардуино общаются по Serial. Помогите ламеру.

timrock
Offline
Зарегистрирован: 29.05.2012

Руки уже чешутся!! Хочу юзать. Подкину  500 рубликов на телефон тому кто поможет поскорей начать.  
Задание такое:
 

1. Описать подробно circuit. Куда ТХ куда RX.... и т.д.
 

2. Написать код для ардуино в котором внешний МК сообщает иногда одну из трёх команд: 

80h (128) - - - - - > на тебе первую команду
8fh (143) - - - - - >  на тебе вторую команду
 26h (38)- - - - - > на тебе третью команду
 

А ардуина отвечает :

в ответ на первую < - - - - - 02h (02)
в ответ на вторую< - - - - - 02h (02)
в ответ на трерью< - - - - - 0fh (15)
 

Я буду потом править код под свои нужды. Поэтому очень желательно что бы все было в десятичной системе ибо мне так привычней (я в шестнадцатеричной не секу не робот).
 

maksim
Offline
Зарегистрирован: 12.02.2012

А команды в какой момент должны отсылаться? через определенные промежутки времени или по нажатию на кнопку? или еще как?

maksim
Offline
Зарегистрирован: 12.02.2012

У вас макетка есть, что бы второй МК запустить?

leshak
Offline
Зарегистрирован: 29.09.2011

  > Описать подробно 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);// послыаем его
     }

  }
}

 

 

maksim
Offline
Зарегистрирован: 12.02.2012

leshak пишет:
Тогда TX дуины -> PD0 (вторая нога) , RX -> PD1 (треться нога).

И не забываем про землю так как если источники питания разные то связи не будет.

leshak
Offline
Зарегистрирован: 29.09.2011

 Упс.... в отсылающей, забыл переход на следующую команду сделать.

Вот так правильней:

#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();// прочитали ответ
     
     // что-то делаем с ответом, тут пишите свою логику
  }


}

 

timrock
Offline
Зарегистрирован: 29.05.2012

Внешний МК внутри корпуса я туда не лазил. имеет культурные выходы обозначенные как RX, TX, G. Команды шлет произвольно перерабатывая инфу от своих внешних датчиков .  

timrock
Offline
Зарегистрирован: 29.05.2012

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

timrock
Offline
Зарегистрирован: 29.05.2012

byte bt=Serial.read() // не могу поверить. неужели в одной строчке идет обявление переменной  и тут же присвоение значения???? 

может вынести об явление  переменной до void setup(). Там обычно идут  всякие int... 

сорри за чайниковские вопросы..... развейте сомнения. 

leshak
Offline
Зарегистрирован: 29.09.2011

 > не могу поверить.

А зачем верить? Можно же в ардуиноIDE вставить и убедится что компилятор не ругается.

Да и что в этом такого "удивительного"? Нелогиченого же ничего нет. Зачем писать две строки, где можно одну?

>может вынести об явление переменной до void setup(). Там обычно идут всякие int...

Если так спокойней - можно. Ничего страшного не случится. 

Так как в ардуино скетчи относительно небольшого размера (десятки-сотни строк) - многие так и делают. А вот если "программа большая", то глобальные переменны (это те самые обычно идут всякие int...) - становятся злом. Если функций, всяких - сотни. То уже уследить что-бы две разные функции не начали использовать переменную по разному и не "мешали друг-другу" - уже сложней.

В одной функции counter - означает счетчик диодов, в другой - счетчик кнопок. Есть вероятность "не уследить" :(

Вообщем, "хороший стиль" - использовать глобальные переменные только когда "без них никак" (или нучно срочно какой-то костыль влепить). 

Но еще раз - в ардуино-скетчах придерживаться этого "фен-шуя" не критично. Из-за их малого объема, "конфликт переменных" как правило виден простым взглядом.

timrock
Offline
Зарегистрирован: 29.05.2012

окей. Спасибо, leshak. Хорошая работа. жду номер Вашего телефона. mig23@list.ru

leshak
Offline
Зарегистрирован: 29.09.2011

 

timrock пишет:

отсылающей стороны код мне не нужен. это готовое устройство от поставщика и я его не кодирую. когда придет команда практически от нее не известно. известны лишь варианты ожидаемых команд. Пожалуйста поправьте все если нужно с учетом последнего замечания.

Ну не нужен, так не нужен. Что поправлять-то? Не берите его, да и все. Считайте что я его не писал :)

timrock пишет:

А и совсем забыл я использую ардуину программирую в стандартном приложении от разработчиков Ардуины. В средствах разработки где используется чистый С я ни чего не понимаю (не знаю даже критично ли последее замечание)

Совершенно не критично. Наоборот. Так как это ардуино форум, то если не оговоренно другое подразумевается что вы используете именно ArduinoIDE от разработчиков.

timrock пишет:

и сообщите мне свой мобильный номер и Вашего оператора, для перевода денег

Не, ну на форуме светить такое я точно не буду. Если хотите напишите на alxarduino[ЗАКРУЧЕННОЕ_УХО]gmail.com

Укажите ваш формуный ник, что-бы я понял о чем речь идет. В идеале - можете сразу дать скайп - свяжемся, обсудим. Может еще какие-то вопросы у вас возникнут. Но это не обязательно. Вообщем-то ответы на форуме бесплатны. Так что деньги - сугубо по вашей доброй воле ;)

leshak
Offline
Зарегистрирован: 29.09.2011

 Да и раз вы не управляете передающем устройством, вам нужно, еще выяснить на какой скорости оно передает и подправить строчку 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

leshak
Offline
Зарегистрирован: 29.09.2011

timrock пишет:

Внешний МК внутри корпуса я туда не лазил. имеет культурные выходы обозначенные как RX, TX, G. Команды шлет произвольно перерабатывая инфу от своих внешних датчиков .  

Э.... на всяк случай. Проверте вольтметром что там у вас на пинах. Что-бы случайно не оказалось что это RX,TX какого-нибудь RS232 12-ти вольтового. Тогда нужно еще уровни согласовать, что-бы входы дуины не выпалить.

Или, наоборот. Там входы 3-х вольтовые, а вы вкатите туда дуиной 5v. Тоже может быть череповато.

timrock
Offline
Зарегистрирован: 29.05.2012

НИ когда не замерял раньше цифру. Между чем и чем замерять? А что ждать от вольтметра? Если выходы 5в за счет добавления битов патенциалом 0в показания усредняться до  2.5в.  А если выводы 3х вольтовые то вообще 1.5в покажет? 

leshak
Offline
Зарегистрирован: 29.09.2011

Замер всегда делается между "точкой замера" и "землей". В вашем случае - между пином и "общей землей".

> усредняться до 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" и т.п. В этом случае опять,таки "можно подключать на прямую". Если такого не сказанно - смотрим предыдущий пункт.

leshak
Offline
Зарегистрирован: 29.09.2011

 А можно еще саму ардуину заюзать в качестве вольтметра.

Что-бы отличить 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 (смотря на сколько меньше).

timrock
Offline
Зарегистрирован: 29.05.2012

Спасибо. Очень исчерпывающе. Я бы даже сказал христоматийно!