Arduino:Примеры/SerialCallResponse

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску

Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.


Последовательная передача данных методом вызова и ответа (рукопожатия) [1]

Этот пример демонстрирует многобайтную передачу данных от Arduino к компьютеру при помощи метода вызова и ответа (рукопожатия). При запуске скетч отправляет ASCII-символ «А» (байт со значением «65») и повторяет это до тех пор, пока компьютер не даст ответ. Получив его, он отправляет на компьютер еще три байта (по одному от каждого из трех датчиков) и снова ждет ответа от компьютера. Для того, чтобы увидеть полученные данные, можно воспользоваться окном Serial Monitor, а можно прочитать их программой Processing (см. код ниже), Flash, PD, Max/MSP (см. код ниже) и т.д.

Необходимое оборудование

  • Плата Arduino;
  • Два аналоговых датчика (подойдут потенциометры, фотоэлементы, силоизмерительные резисторы и т.д.);
  • Одна кнопка;
  • Три резистора на 10 кОм;
  • Макетная плата Breadboard;
  • Провода-перемычки;

Необходимое ПО

Цепь

Подсоедините аналоговые датчики к 0-ому и 1-ому входным аналоговым контактам, а также к двум 10 кОм резисторам, ведущим к «земле» – для того, чтобы создать два делителя напряжения. Кнопку подключите ко 2-ому цифровому контакту и к 10 кОм резистору, тоже ведущему к «земле».

Схема

Код к Arduino

/*
 Последовательная передача данных методом вызова и ответа
 Язык – Wiring/Arduino
 
 Эта программа при запуске отправляет ASCII-символ «А» (байт со значением «65») и повторяет это, пока в ответ тоже не получит данные. 
 Затем, дождавшись байта, переданного через последовательный порт, она передает компьютеру три значения от аналоговых датчиков.
 Спасибо Грегу Шакару (Greg Shakar) и Скотту Фитцджеральду (Scott Fitzgerald) за поправки.
 
   Цепь:
 * потенциометры, подключенные к 0-ому и 1-ому входным аналоговым контактам
 * кнопка, подключенная ко 2-ому цифровому контакту
 
 Создан 26 сентября 2005 Томом Иго (Tom Igoe),
 модифицирован 24 апреля 2012 Томом Иго (Tom Igoe)
 и Скоттом Фитцджеральдом (Scott Fitzgerald).

 Этот код не защищен авторским правом.

 http://www.arduino.cc/en/Tutorial/SerialCallResponse

 */

int firstSensor = 0;    // первый аналоговый датчик
int secondSensor = 0;   // второй аналоговый датчик
int thirdSensor = 0;    // цифровой датчик
int inByte = 0;         // переменная для байта, передаваемого через последовательный порт

void setup()
{
  // начинаем последовательную передачу данных со скоростью 9600 бит/сек:
  Serial.begin(9600);
  while (!Serial) {
    ; // ждем подключения последовательного порта (это нужно только для Leonardo)
  }

  pinMode(2, INPUT);   // цифровой датчик подключен ко 2-ому цифровому контакту
  establishContact();  // отправляем байт, чтобы установить связь; делаем так, пока не приходит ответ 
}

void loop()
{
  // если получаем нужный байт, считываем данные с аналоговых датчиков:
  if (Serial.available() > 0) {
    // получаем байт от компьютера:
    inByte = Serial.read();
    // считываем данные на первом аналоговом контакте, а затем делим их на 4, чтобы получить число в диапазоне от 0 до 255:
    firstSensor = analogRead(A0)/4;
    // делаем задержку в 10 миллисекунд, чтобы аналогово-цифровой преобразователь немного «отдохнул»:
    delay(10);
    // считываем данные на втором аналоговом контакте, а затем делим их на 4, чтобы получить число с диапазоне от 0 до 255:
    secondSensor = analogRead(1)/4;
    // считываем данные с кнопки, присваиваем ей одно из двух значений – 0 или 255L
    thirdSensor = map(digitalRead(2), 0, 1, 0, 255);  
    // передаем компьютеру данные от датчиков:
    Serial.write(firstSensor);
    Serial.write(secondSensor);
    Serial.write(thirdSensor);               
  }
}

void establishContact() {
  while (Serial.available() <= 0) {
    Serial.print('A');   // отсылаем прописную «А»
    delay(300);
  }
}

Код к Processing

/* Скетч к Processing для этого примера: */

// Этот код не защищен авторским правом.

import processing.serial.*;

int bgcolor;                 // фоновый цвет
int fgcolor;                 // цвет заливки
Serial myPort;                       // последовательный порт
int[] serialInArray = new int[3];    // переменная, куда мы запишем значение, которое получили
int serialCount = 0;                 // переменная, в которой мы будем считать, сколько байтов получили
int xpos, ypos;                  // стартовая позиция для шарика
boolean firstContact = false;        // был ли первый контакт с Arduino или нет (по умолчанию false, т.е. «нет»)

void setup() {
  size(256, 256);  // размер экрана
  noStroke();      // контур не рисуем 

  // задаем стартовую позицию шарика (в середине экрана)
  xpos = width/2;
  ypos = height/2;

  // выводим список последовательных портов (в целях отладки):
  println(Serial.list());

  // я знаю, что первый последовательный порт на моем Mac – 
  // это всегда FDTI-адаптер, поэтому я сразу открываю Serial.list()[0].
  // на Windows-устройствах это, как правило, открывает порт COM1.
  // впрочем, вам нужно тот порт, который используется у вас.
  String portName = Serial.list()[0];
  myPort = new Serial(this, portName, 9600);
}

void draw() {
  background(bgcolor);
  fill(fgcolor);
  // рисуем фигуру (т.е. шарик)
  ellipse(xpos, ypos, 20, 20);
}

void serialEvent(Serial myPort) {
  // считываем байт, который пришел по последовательному порту:
  int inByte = myPort.read();
  // если это первый полученный байт и это «А»,
  // очищаем буфер последовательного порта
  // и отмечаем, что у нас состоялся первый контакт с микроконтроллером (т.е. с Arduino).
  // в противном случае добавляем пришедший байт в массив
  if (firstContact == false) {
    if (inByte == 'A') { 
      myPort.clear();          // очищаем буфер последовательного порта
      firstContact = true;     // пишем, что был первый контакт с микроконтроллером
      myPort.write('A');       // запрашиваем еще
    } 
  } 
  else {
    // добавляем в массив последний байт, полученный по последовательному порту:
    serialInArray[serialCount] = inByte;
    serialCount++;

    // если получили три байта:
    if (serialCount > 2 ) {
      xpos = serialInArray[0];
      ypos = serialInArray[1];
      fgcolor = serialInArray[2];

      // выводим эти данные (только в целях отладки):
      println(xpos + "\t" + ypos + "\t" + fgcolor);

      // отсылаем прописную «А» в качестве запроса на новые данные от датчиков:
      myPort.write('A');
      // сбрасываем значение в serialCount:
      serialCount = 0;
    }
  }
}

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

Код к Max

/* Патч к Max/MSP (версия 5) для запуска этого примера: */

----------begin_max5_patcher----------
3908.3oc6ckziiaiE9b0+J3XjCIXpp.WzZNMURv.jCInQ5fYNjNngrDssRKK
4nkp6JA4+973hrkrsjncKu0SRiXasQ83G+dKj7QV+4qtaxzrOxKlf9Zzuft6
t+7U2cm7ThSbm936lrL3igIAExaaRJ+CYS+sI2qtTI+ikxSuBMKNojm+N3D4
Aua5KkPwpuoUAkgKhSm+tbdXo5cQXVOhuGwrohuHD4WT7iXzupen3HY4BuqG
rH0kzrrzxzfkb4kdJONHo9JoUKiSS3kRgjt4jYUk0mkznPJh+CYgHewpSqty
xWVwUh3jIqkEYEfmqQEMr.ETbB+YddQbVZix+tIAqV03z203QDX4ukIKHm6W
ep3T0ovqOUN+435m2Rcx+5U0E+FTzVBh9xOsHXIh5YuADg1x4IYgumG0r3mj
shmFmtJmWvSKCJ0um0WNhOKnJo7c6GmZe8YAg7Ne381Rc2j44wQYoBgn0SJN
c8qCHH1RhQqJi7NRCVsmGt.pGUESCxE31zDdCV.PRyxRZeo0MU.WOHMdYPIu
LVIrT75BMd4p73zxVuHdZ.TFKJByyRRZUTpq77dtRDzZFx+PbT4BYY0DJgaO
dUcSvj0XTT7bdQY6yUFLun8YZo71jl0TIt042RYNLa4RfCTWfsznKWDWfJpl
tJHrbgV6t.AZInfzWP.4INpJHA8za91u+6QN1nk7hh.PpQwonxEbTAWzpilV
MimilkmsDtPbo3TPiUdY0pGa9ZShS4gYUJz1pwE1iwCpxbAgJI9DGGwWNzFT
ksLf3z7M0MybG6Hj1WngsD7VEXS8j5q7Wu5U0+39ir8QJJS5GMHdtRimL4m1
0e1EVX0YsE2YssINriYRoFRyWVMoRRUGQvnkmms3pnXDYHbBKMPpIOL5i1s8
3rMPwFcRCsGRyPH780.8HBnpWz.vlEQBWJ+0CSunehJSmJxiIZRtNGhhDYrU
jt3ZQyA2fHJhZDifXIQHUHH8oGYgOREI5nqHIzhFWUndPyBdB3VzHJGwUhkV
rgvRl2UCVNMHcd234lf1DN16HFEIdHt99A5hrp7v5WWMSBQZgMP.Tkwoqig8
W1.Sn1f3h3nn1wLpBypPDzlJ7XinEGkLiMPloWOhrgR7dpZWJQV1faDy35Qj
MThMFkWFGsJChQPqrQp8iorV6Q28HBVF4nMVDJj7f1xyYACFScisg.ruLHOW
uMUS4Am4pI4PTnHi.6bi02HNzSYnDBe4cgAgKzRk1jc8PJLoH3Ydz6.Q.7K8
tfxx73oUkJq1MGuCy5TpAi.POWZ3AenidLOOIaZPhdjZVW3sdk6LXEGzHb7p
Mfr7SEy3SXHyBSxJ3J2ncNNYVJsXG6Me10nj4cfCRFdTFjLo7q3SiCpjjEDM
.nvra.GN39.E2CDTHWXPo8.xzfqrHCHKnf5QUYUVdoZPUjCSC7LU8.XtTUXl
X8vr51GjwFGLC2AlMdLkU4RiaRrnmJuiudnDk0ZW+9p6TuKBe433JUCzp6fU
iOF0SUk2UQYUPNTEkiZubvKa1tsmgL5SCTXGHnnG0CceLpkpR9Rs28IUESWl
EwWNKfHlg.zj6Ee7S+nE8A+m9F7Cu40u9gMm+aRp3kYYkKd3GDOz5y+c7b96
K9gfvuIK68uNO6g2vUUL80WxihCVFD9vlB30e2SOrmxUb527RZ3nZNrljGrR
70vs1J9suWuZ3zaHVdG3RIJLgGj2Gfn6TcGcstEfvtH.hpFLlnBndjOLGQAI
z98BXc6yQxghmOn6gZqj0ShPOXhynLOjzCESt+XwE8TxrCvrdXo16rqnLgvb
HaFmbh29QD+K0DyNdjDwvzQL.NXpoMvoOBxkger0HwMRQbpbCh91fjjG9Idw
prTH9SzaSea5a.GQEPnnh43WNefMlsOgx18n.vgUNO.tKl7tDyI3iHzafJHZ
VVNedVEbGgYIY42i93prB0i7B7KT1LnnCiyAiinpBnsPV7OG.tYKfBsrJOkG
UG5aq26iJw6GyJ4eM5mEgEKaNQPMEBUp.t8.krplOVTlZdJAW27bjvGK7p2p
HQPgLOSJDYv4E9gQBYBjMUselRxDy+4WplIzm9JQAWOEmfb.E364B43CAwp5
uRRDEv8hWXprjADMUOYpOg9.bVQpEfhKgGCnAnk.rghBJCdTVICA3sDvAhE5
oU4hf67ea5zWPuILqrD8uiK+i477fjHIt9y.V88yy3uMsZUj7wnxGKNAdPx5
fAZMErDZOcJU4M01WFQokix.pKa+JE1WacmnKFeYd7b.0PeIzB8Kk+5WIZpB
Ejt34KJeHgOCh4HK8Y3QiAkAfs8TRhhOkG7AAGQf0qxyfmQxa+PLb8Ex.2PS
4BdO5GB9Hvg+cfJCMofAIMu9Qz+UPCjckqVJlEmyA8Bf.rC6.3hAEuG8TdTU
bZljQ0nr1ayIqmTwQYfyRGafZhur5vfuyMSqYNWmtAPwWHalDSuUgT0Bosh.
JpAR89Y6Ez5QEfPTQO4J0DHLInIliz8BZV2JfV3Bd36qsQwAVVXbr1BGXp6s
Sd5sSDruo74wofx.HxUgxQwTnMLqTXvRmiGh2PUZr5pBynKChjl6feNUjSRn
hEUfRPT1GfG9Ik4TQBm.hEZZ.bc38HjAMKGzDRijEm1ifx1dbgzQyKh6FZc3
wOCkRJH+KUh0daWs6wzltWx1puXxlWW6NZWY2JiTBzzILRIANku02NourySM
VI1VJTvQZff32AJr+dS9e34QAoA6EGXlGFH9yk7yyQAlVd3SR94g+TxOu1sU
Flgd6ICI96LzazyPu1cgqsZ8r74SgF.65+efbMf4pGHT7lgHh30Sha3N5Ia.
oqjMf7nsuMwycf7iYDybiAAVr3eC.oTMjpzEr8GDRc9bFRGHYXDrzg.Tlx+q
NW8TY1IkzCfZ2IftkQstbB08HUezoDS+oFyI.cWIhWBaDiUo7qIrDO7f.L6n
AXqCmyNT9act.z+Iv.GR0uES0ZXfjdz.IczAxQOUR+zvRsUTigRxmyPYeNlj
yXv8Peef2ZFzuLzWPPeAE8ELzWXYlhe8WzAcUg+b1UkIoCLzIH60zwASGXau
a1Dq2nUY.sox4vng+m0nACePngC9lEMLZMBPodOxf+yx5d4uMCTHm3kJvIIG
jcLMedEQldkjpoBkQyjY1Hk.hmSY95Iwos8NDb9VSlIWOIntqgxryUjL6bCJ
y1lli5tWWxrQ7YmqGYlc6shK1iY2dr0wtNjYxgHyzaq0OznY235awCr8zSz6
EGd1QNUKf.74dADTBbTbeotjpW95IolY0WpKYONY8M83Rx2MChx3fL+iG5Mm
tXpdmvXj8uTvaAL1WjbbarQD4Z6kXBpnm6a69oKV2PY9WY174IbC3CaRQ9iK
Q4sYGQpwdtZ5wFrc7n569.M83OOR5ydSB1ZcAWCxdbKuavz9LILxfD.wWO.W
Nq+Zu4Es+AP6s5p9jDWH8ET+c85+XbW0.N1nDCTD7U4DGc6ohnU019fS7kQ0
o43luuOGjv5agHp0DT.CysOfgLR3xXlXTUKm16RivRsn3z0O6cl3YScAvtrb
hwekGB7BZuqESUzBJWmCvK7t9HF8Ts6cUAPoFWso3aP8ApWyJ3wqOPo2pJDC
BQ0NI0Pj8QCQ2r1L5vKaU5lDRYX7yRur1UYYZmJQ9iDHwN9dndB5n5ejflmm
UsBwLHnDkKXWRuAkb3NeuzqRstiQGP.fCQFdHNzaE.8u58Nz9svFE9SGIE1X
kv9Iwfl1BdNWjA7xcThsWCS847loyFD8pZq2E2F04lYULzBTDYhrFSDDJdjo
fisN2NUN26e4xRu51zD5ZseJ4HC63WyIX6jRqsp0jangBnK.Qlo58PCpWevt
ahzqK7fbKsdX6R64aao8LmWhBPh9jKVAPMzb5a2cV6opdWHneMmqMEmAGsPh
ieigIjV+4gF1GgbMNXg+NH44YaRYyd..S1ThHzKhFwwGRaWVITqyj9FvPqMT
d0pDuSqDrOGF.Uogf.juCFi9WAUkYR+rFPanDcPG8SbrtjyG03ZQ8m3AqC5H
NcUUoXSwVrqXKVcZu.5ZnkwIfIVdXVZTwAuTTUiYuxwjZDK6ZgnRtYV8tJmP
hEcuXgz2Goxyaiw35UkaWbpqtfzD02oUkkYqi.YQbZqIIWrIljFolsdmMKFR
wCJ2+DTn.9QlkOld+d9Qy9IJdpLfy05Ik2b8GsG9h8rdm1ZFx1FrmmlA2snw
qI9Mcdi2nr6q3Gc87nLawurbw1dda+tMyGJ9HaQmlkGwy6davisMgrkM65oz
eulfYCzG46am8tSDK144xV4cEvVMTRXq9CIX8+ALNWb6sttKNkiZetnbz+lx
cQnb1Nds2C0tvLNe14hwQtxYbxhqc17qHfamUcZZ3NYSWqjJuiDoizZ+ud2j
naRK4k3346IIVdR1kKiQjM39adMamvc6n+Xp36Yf3SIGh3uKbquqs1JksTII
kuJ7RrZSFb2Cn9j5a6DT8cMo0iczU+lsYaU8YNVh5k5uzJLU26ZcfuJE6XLY
0mcRp9NTCp+L+Ap+in7Xf3b9jFQBLtIY06PbrGhcrU6N00Qlaf9N0+QPo9nS
P6qsI7aYNLSNOHpsAxis0ggnZLjYqyyFkdSqinVsPaqSDZaYBZ6c93uLCjGm
iCroJVLzU45iNE.pIUfs3TWb.0FejHp9uANr0GcJPTroFDNOHpkIweLnI1QT
dHl3P7LhOF3Ahd9rnvLwAMy5JSdNezGlsIsW9mW44r26js+alhxjlkdhN0YE
YqiH5MTeWo6D4Qm.ieLS7OynmuVGSbmbFUlnWWhiQlhOeN+Yl35bq.tGo9JR
cj8AVqdz7nSgVB9zNj.FTOU68o5d9KO5TUOGxVMw+jTO8T6wqD0hEiHsOJO5
TTOMoS.zlqN0SpZjz6GcH05ylVM0jwuidlkmAif374ih5M5QPfccr8Hqifff
otN8pt3hUcaWu8nosBhwmD0Epw5KmoF.poxy4YHbnjqfPJqcM3Y2vun7nS.i
f3eETiqcRX2LR.4QmhZrkoCSGwzZrqKHrVR8caari+55d2caPqmq5n.ywe8Q
WrZL9fpwVXeaogMByE6y1SMdjk+gbavbN7fYvVtt1C2XwHJSzpk+tidUO25H
UB9onw9mlFQ10fhpZBaDatcMTTEGcJpwzqg92qqiVtM6Cu0IRQ0ndEdfCAqV
l0qYAUmPrctbxO4XCuPMa1asYzKDks1D52ZCne6Mednz9qW8+.vfqkDA
-----------end_max5_patcher-----------

Скопируйте патч к Max (он указан выше) и вставьте его в новое окно.

См.также

  1. serial.begin()
  2. serial.available()
  3. serial.print()
  4. analogRead()
  5. Dimmer
  6. Graph
  7. Physical Pixel
  8. Virtual Color Mixer
  9. Serial Call and Response ASCII
  10. Serial Input (Switch (case) Statement)

Внешние ссылки