Прием и передача массива по uart
- Войдите на сайт для отправки комментариев
Чт, 20/02/2014 - 17:03
Уважаумые форумчане, помогите решить вопрос по приему и передачи массива значений. Написал скетчи, а работать не хочет. Делаю дистанционное управление танком, это проба передачи данных управления. Передача:
byte buf[6];
void setup()
{
Serial.begin(9600);
}
void loop()
{
buf[0] = map(analogRead(0), 0, 1023, 0, 254);
buf[1] = map(analogRead(1), 0, 1023, 0, 254);
buf[2] = map(analogRead(2), 0, 1023, 0, 254);
buf[3] = digitalRead(A3);
buf[4] = digitalRead(A4);
buf[5] = digitalRead(A5);
Serial.write(0xff); // synchronize
for (int i=0; i < sizeof(buf); i++)
{
Serial.write(buf[i]);
}
}
Прием:
int out[2];
char buf[5];
void setup() {
Serial.begin(9600);
out[0] = (9);
out[1] = (10);
out[2] = (11);
for (int q = 3; q <= 5; q++)
{
pinMode(q, OUTPUT);
digitalWrite(q, LOW);
}
}
void loop() {
if (Serial.available()>sizeof(buf))
{
byte x = Serial.read();
if (0xff == x) // sync byte
{
for (int i =0; i <= 5; i++)
{
x = Serial.read();
analogWrite(out[i],x);
digitalWrite(i,x);
}
}
}
}
Подскажите пожал
вот на передачу.
я честно сказать точно не помню как пишется. но там что то вроде должно быть.
максим тебе точно скажет как там правильно пишется
byte buf[6]; void setup() { Serial.begin(9600); } void loop() { buf[0] = map(analogRead(0), 0, 1023, 0, 254); buf[1] = map(analogRead(1), 0, 1023, 0, 254); buf[2] = map(analogRead(2), 0, 1023, 0, 254); buf[3] = digitalRead(A3); buf[4] = digitalRead(A4); buf[5] = digitalRead(A5); Serial.write(0xff); // synchronize Serial.write(buf[], 6); }Передатчик вроде работает, в мониторе ком порта данные идут нормально. Мне кажется, что я где-то с приемником накосячил. Если поменять analogWrite на servo[i].write(x), то все работает.
так у вас ваш или тот что я предложил нормлаьно работает?
если вы управляете мотором при чем здесь servo библиотека?
и по моему в приемнике неправильно сделано. но я не уверен и не буду утверждать
Передатчик нормально работает(Вроде). Servo, для примера. Я тоже считаю, что проблема где-то в приемнике, но не могу понять где((
создайте массив. запишите туда сначала все значения. а потом уже управляйте моторами и чем хотите
и еще добавьте ответ на передатчик что все получено. и можно снова слать. а то передатчик все время шлет, а приемник может еще не успел обработать. буфер переполнится. данные потеряются
Не совсем понял про массив((.
Вот так работае идеально, передача:
byte buf[4]; void setup() { Serial.begin(9600); } void loop() { buf[0] = map(analogRead(0), 0, 1023, 0, 180); buf[1] = map(analogRead(1), 0, 1023, 0, 180); buf[2] = map(analogRead(2), 0, 1023, 0, 180); buf[3] = map(analogRead(3), 0, 1023, 0, 180); Serial.write(0xff); // synchronize for (int i=0; i < sizeof(buf); i++) { Serial.write(buf[i]); } }Прием:
#include <Servo.h> Servo servo[4]; char buf[4]; void setup() { servo[0].attach(3); servo[1].attach(7); servo[2].attach(9); servo[3].attach(11); Serial.begin(9600); } void loop() { if (Serial.available()>sizeof(buf)) { byte x = Serial.read(); if (0xff == x) // sync byte { for (int i =0; i < sizeof(buf); i++) { x = Serial.read(); servo[i].write(x); } } } }И для обмена нужно двухстороннюю передачу делать, а у меня с трансиверами проблемы. Если по почте заказывать, месяц ждать, весь интерес пройдет, а до города ехать 650 км. На севере живу. А кто такой Максим? Как его пригласить в наш диалог, или связаться с ним?
в самом первом посте - у вас буферы на передачу и на прием разной длины
и вот это как-то.... ммм... одним словом, так нельзя :)
Буферы делал одинаковые, просто при вставке один код старый взял. Даже при одинаковых размерах не работает.
Что здесь не так? Если не считать, что вместо int out [2] нужно поставить int out [3]
byte buf[4]; void setup() { Serial.begin(9600); } void loop() { for(int i=0;i<4;i++){ buf[i] = map(analogRead(i), 0, 1023, 0, 180); } Serial.write(0xff); // synchronize for (int i=0; i < sizeof(buf); i++) { Serial.write(buf[i]); } }чтение можно в цикл засунуть. только непонятно как вы считываете аналоговое значение с цифрового входа? что за ардуина такая
Это все работает. То, что вы сейчас написали, тот же код только немного по другому оформлен. А в каком месте я считываю аналог с цифры?????
analogRead (0) = analogRead (A0) - всЁ равно...
digitalRead(A0) = digitalRead (14) (uno, duemilanove, decimila) аналогично
Этого ни кто и не отрицал. Я считываю цифру с аналога, это нормально. Мне просто удобнее писать А0 и т.д. Просто у меня Mega и аналог там подписан как А0 и т.д.
Только непонятно как в этом цикле написать A0, A1, A2......
for(int i=0;i<4;i++){ buf[i] = map(analogRead(i), 0, 1023, 0, 180); }Вряд-ли for ( int i = A0 ; i < A4 ; i++) ;)
Буферы делал одинаковые, просто при вставке один код старый взял. Даже при одинаковых размерах не работает.
Что здесь не так? Если не считать, что вместо int out [2] нужно поставить int out [3]
а это, по вашему, ерунда? ошибки с памятью (невыделение, запись низвестно куда, чтение неизвестно откуда) - значительная доля всех глюков.
Да это не важно. Что автоматом вместо i расставятся цифры, что я явно задам, передатчик работает. На данный момент я это знаю точно.
А я не сказал, что это ерунда. Наоборот, я спросил, что там не так.
Только непонятно как в этом цикле написать A0, A1, A2......
for(int i=0;i<4;i++){ buf[i] = map(analogRead(i), 0, 1023, 0, 180); }Вряд-ли for ( int i = A0 ; i < A4 ; i++) ;)
Это можно записать как:
for (int i=0; i<4; i++)
{
buf[i] = map(analogRead(Ai), 0, 1023, 0, 180);
}
Да это не важно
вы не понимаете основ использования памяти. вылезание за границы массива является грубейшей ошибкой. если на пальцах, то нельзя впихивать невпихуемое
Да это не важно
вы не понимаете основ использования памяти. вылезание за границы массива является грубейшей ошибкой. если на пальцах, то нельзя впихивать невпихуемое
Это написано было для trembo. А у вас я спросил, как можно по другому сделать, чтобы впихнулось)) И вообще, что-то со всем кодом не так. За ночь сделал много открытий на этом форуме, сейчас попробовал по другому сделать, но... Снова не нравится. Какие-то непонятные скачки по портам где выхода.
Вот код приемника:
int pot1x = 9; int pot1y = 10; int pot2x = 11; int knopka1 = 3; int knopka2 = 4; int knopka3 = 5; int knopka4 = 6; int knopka5 = 7; int knopka6 = 8; void setup() { Serial.begin(9600); pinMode(knopka1, OUTPUT); digitalWrite(knopka1, LOW); pinMode(knopka2, OUTPUT); digitalWrite(knopka2, LOW); pinMode(knopka3, OUTPUT); digitalWrite(knopka3, LOW); pinMode(knopka4, OUTPUT); digitalWrite(knopka4, LOW); pinMode(knopka5, OUTPUT); digitalWrite(knopka5, LOW); pinMode(knopka6, OUTPUT); digitalWrite(knopka6, LOW); } void loop() { if(Serial.available() && Serial.read() == 'a') { int a = Serial.read(); analogWrite(pot1x,a); Serial.println('pot1x'); } if(Serial.available() && Serial.read() == 'b') { int b = Serial.read(); analogWrite(pot1y,b); Serial.println('pot1y'); } if(Serial.available() && Serial.read() == 'c') { int c = Serial.read(); analogWrite(pot2x,c); Serial.println('pot2x'); } if(Serial.available() && Serial.read() == 'd') { int d = Serial.read(); digitalWrite(knopka1,d); Serial.println('pot2x'); } if(Serial.available() && Serial.read() == 'e') { int e = Serial.read(); digitalWrite(knopka2,e); Serial.println('knopka2'); } if(Serial.available() && Serial.read() == 'f') { int f = Serial.read(); digitalWrite(knopka3,f); Serial.println('knopka3'); } if(Serial.available() && Serial.read() == 'g') { int g = Serial.read(); digitalWrite(knopka4,g); Serial.println('knopka4'); } if(Serial.available() && Serial.read() == 'h') { int h = Serial.read(); digitalWrite(knopka5,h); Serial.println('knopka5'); } if(Serial.available() && Serial.read() == 'i') { int i = Serial.read(); digitalWrite(knopka6,i); Serial.println('knopka6'); } delay(10); }А это передатчик:
int pot1x = 0; //Обьявляем А0 аналоговый пин считывания показаний потенциометра1 (ось x) int pot1y = 1; //Обьявляем А1 аналоговый пин считывания показаний потенциометра1 (ось y) int pot2x = 2; //Обьявляем А0 аналоговый пин считывания показаний потенциометра2 (ось x) int knopka1 = 3; //кнопка1 подключена к 3 цифровому контакту int knopka2 = 4; //кнопка2 подключена к 4 цифровому контакту int knopka3 = 5; //кнопка3 подключена к 5 цифровому контакту int knopka4 = 6; //кнопка4 подключена к 6 цифровому контакту int knopka5 = 7; //кнопка7 подключена к 7 цифровому контакту int knopka6 = 8; //кнопка8 подключена к 8 цифровому контакту void setup() { analogReference(DEFAULT); Serial.begin(9600); pinMode(knopka1, INPUT); digitalWrite(knopka1, HIGH); pinMode(knopka2, INPUT); digitalWrite(knopka2, HIGH); pinMode(knopka3, INPUT); digitalWrite(knopka3, HIGH); pinMode(knopka4, INPUT); digitalWrite(knopka4, HIGH); pinMode(knopka5, INPUT); digitalWrite(knopka5, HIGH); pinMode(knopka6, INPUT); digitalWrite(knopka6, HIGH); } void loop() { // Отправляем в сериал-порт данные в двоичном виде. Serial.write('a'); //метка начала передачи последовательности команд Serial.write(map(analogRead(pot1x), 0, 1023, 0, 254)); //потенциометр 1x Serial.write('b'); Serial.write(map(analogRead(pot1y), 0, 1023, 0, 254)); //потенциометр 1y Serial.write('c'); Serial.write(map(analogRead(pot2x), 0, 1023, 0, 254)); //... Serial.write('d'); Serial.write(digitalRead(knopka1)); //кнопка 1 Serial.write('e'); Serial.write(digitalRead(knopka2)); //кнопка 2 Serial.write('f'); Serial.write(digitalRead(knopka3)); //... Serial.write('g'); Serial.write(digitalRead(knopka4)); Serial.write('h'); Serial.write(digitalRead(knopka5)); Serial.write('i'); Serial.write(digitalRead(knopka6)); delay(50); }Это можно записать как:
for (int i=0; i<4; i++)
{
buf[i] = map(analogRead(Ai), 0, 1023, 0, 180);
}
Проверяли? Компилится? i и Ai - ведь это ДВЕ разные переменные.
Это можно записать как:
for (int i=0; i<4; i++)
{
buf[i] = map(analogRead(Ai), 0, 1023, 0, 180);
}
Нельзя.
Если очень надо то можно так:
for (int i = A0; i < A4; i++) { buf[i-A0] = map(analogRead(i), 0, 1023, 0, 180); }Это можно записать как:
for (int i=0; i<4; i++)
{
buf[i] = map(analogRead(Ai), 0, 1023, 0, 180);
}
Нельзя.
Если очень надо то можно так:
for (int i = A0; i < A4; i++) { buf[i-A0] = map(analogRead(i), 0, 1023, 0, 180); }Да это не в этом проблема. Передатчик работает, номально передает данные. мне их принять надо корректно. И второй вариант кода как-то более рабочий.
Да это не в этом проблема. Передатчик работает, номально передает данные. мне их принять надо корректно. И второй вариант кода как-то более рабочий.
А с передачей данных всегда проще, чем с приемом. Тут главное понимать, что вы работаете с асинхронным приемо-передатчиком (UART) - т.е. приемнику пофиг когда, как, и примет ли вообще другая сторона посланные данные, он плюнул их в "черную дыру" и забыл. А вот приемник должен уметь каким-то образом определить начало передачи пакета данных и их окончание (или длину), проверить контрольную сумму принятых данных. И второй постулат: приемо-передатчик пересылает данные байтами, хоть вы в прогрмме и можете вызвать какую-либо функцию передачи word, long, float, физически будет передана последовательность байт. Теперь мы стали ближе к понимаю, что при работе с данными нам нужен протокол передачи данных.
От лирики к практике:
1) Не факт, что последний ваш вариант правильней, чем первый. В первом варианте я усмотрел правильную вещь - байт синхронизации пакета данных 0xFF:
buf[0] = map(analogRead(0), 0, 1023, 0, 254); -- тут вначале не понял почему ограничение по 254
Serial.write(0xff);// synchronize -- а теперь понял2) В последнем примере вы передаете сначала символ, а потом данные в диапазоне 0-254, а где гарантия что данные из map() и ваши символы не совпадут, тогда весь прием поедет? А где гарантия, что результат map() и digitalRead() имеет размерность 1 байт и в будущем не изменится?
3) Как надо делать: создаем свой протокол передачи данных. У вас был массив - уже хорошо, но на практике лучше использовать структуру, она гибче в использовании в коде и позволяет создать пакет данных с разными типами/размерностью полей.
Пока кратко, а то позно уже, а мне на рыбалку рано вставать :)
а) Создаем структуру, в которой учитываем следующие поля: 1-2 байта синхронизации - можете свои инициалы впихнуть (будет брэндовый протокол:), длина пакета (определиться с длиной чего?, от и до?), ID сообщения в пакете (вдруг ваш протокол получит развитие в других ваших проекта и будете предавать разные пакеты данных - с разными ID и соответственно с разной структурой пакета), 1-2 байта контрольной суммы (определиться с длиной подсчета от и до?). Со структурой пакета все!
б) Сразу продумываете алгоритм подсчета контрольной суммы. Реализуете ее в коде. Тупо мой пример при работе с бинарным протоколом UBX GPS-приемников фирмы u-blox, для примера:
// Подсчет контрольной суммы сообщений протокола UBX void ubx_set_checksum(byte* bptr, const byte msg_size) { byte CK_A = 0, CK_B = 0; // вычисление ведется, начиная с элемента CLS и до двух байт контрольной суммы bptr+= 2; for( int i = 0; i < msg_size - 4; i++) { CK_A = CK_A + *bptr++; CK_B = CK_B + CK_A; } // for( int i = 0; i < msg_size - 4; i++) // записываем контрольную сумму в структуру сообщения CFG-XXX в byte cka и byte ckb *bptr++ = CK_A; // & 0x00FF; *bptr = CK_B; // & 0x00FF; }в) Передача пакета выглядит примерно так, опять для примера:
// CFG-RATE (0x06 0x08) - Navigation/Measurement Rate Settings boolean send_UBX_CFG_RATE(HardwareSerial &hs, const word measRate = 1000, const word timeRef = 1) { // measRate: Measurement Rate, GPS measurements are taken every measRate milliseconds // timeRef: Alignment to reference time: 0 = UTC time, 1 = GPS time // B5 62 06 08 06 00 E8 03 01 00 01 00 01 39 - 1000 ms = 1 Hz, 1 - GPS time // B5 62 06 08 06 00 F4 01 01 00 01 00 0B 77 - 500 ms = 2 Hz, 1 - GPS time // B5 62 06 08 06 00 FA 00 01 00 01 00 10 96 - 250 ms = 4 Hz, 1 - GPS time // B5 62 06 08 06 00 C8 00 01 00 01 00 DE 6A - 200 ms = 5 Hz, 1 - GPS time cfg_rate.header.bSC1 = 0xB5; cfg_rate.header.bSC2 = 0x62; cfg_rate.header.bCLS = 0x06; cfg_rate.header.bID = 0x08; cfg_rate.header.wLen = 0x0006; cfg_rate.measRate = measRate; cfg_rate.navRate = 0x01; cfg_rate.timeRef = timeRef; ubx_set_checksum((byte*)&cfg_rate, sizeof(cfg_rate)); //SerialPC.println(cfg_rate.cka, HEX); //SerialPC.println(cfg_rate.ckb, HEX); hs.write((byte*)&cfg_rate, sizeof(cfg_rate)); hs.flush(); // тут ловим ответ B5 62 05 01 02 00 06 08 ubx_ack.bCLS = 0x06; // заполняем своим CLS в каждой функции CFG-XXX ubx_ack.bID = 0x08; // заполняем своим ID в каждой функции CFG-XXX return read_UBX_ACK_ACK(hs, (byte*)&ubx_ack, sizeof(ubx_ack)); } // boolean send_UBX_CFG_RATE()г) Прием... все спать, спать, завтра продолжу.
Вот это исчерпывающий ответ))) Минимум воды и максимум нужной информации))
Вот так все работает.
Приемник:
//#include <Servo.h> int speedl = 9; int speedr = 10; int bashnyal = 3; int basnyar = 4; int duloup = 5; int dulodown = 5; int light = 7; int fire = 8; int ff = 12; int fw = 13; int a; int b; int c; int pos; void setup() { Serial.begin(9600); pinMode(bashnyal, OUTPUT); digitalWrite(bashnyal, LOW); pinMode(basnyar, OUTPUT); digitalWrite(basnyar, LOW); pinMode(duloup, OUTPUT); digitalWrite(duloup, LOW); pinMode(dulodown, OUTPUT); digitalWrite(dulodown, LOW); pinMode(light, OUTPUT); digitalWrite(light, LOW); pinMode(fire, OUTPUT); digitalWrite(fire, LOW); pinMode(ff, OUTPUT); digitalWrite(ff, LOW); pinMode(fw, OUTPUT); digitalWrite(fw, LOW); } void loop() { if(Serial.available() && Serial.read() == 'a') { a = Serial.read(); //analogWrite(speedl,a); //analogWrite(speedr,a); } if(Serial.available() && Serial.read() == 'b') { b = Serial.read(); analogWrite(speedl,a+b*2-80); } if(Serial.available() && Serial.read() == 'c') { c = Serial.read(); analogWrite(speedr,a+c*2-80); } if(Serial.available() && Serial.read() == 'd') { int d = Serial.read(); digitalWrite(bashnyal,d); } if(Serial.available() && Serial.read() == 'e') { int e = Serial.read(); digitalWrite(basnyar,e); } if(Serial.available() && Serial.read() == 'f') { int f = Serial.read(); digitalWrite(duloup,f); } if(Serial.available() && Serial.read() == 'g') { int g = Serial.read(); digitalWrite(dulodown,g); } if(Serial.available() && Serial.read() == 'h') { int h = Serial.read(); digitalWrite(light,h); } if(Serial.available() && Serial.read() == 'i') { int i = Serial.read(); digitalWrite(fire,i); } if(Serial.available() && Serial.read() == 'j') { int j = Serial.read(); digitalWrite(ff,j); } if(Serial.available() && Serial.read() == 'k') { int k = Serial.read(); digitalWrite(fw,k); } delay(50); }Передатчик:
int pot1x = 0; int pot1y = 1; int pot2x = 2; int ff = 3; int fw = 4; int knopka1 = 3; int knopka2 = 4 int knopka3 = 5; int knopka4 = 6; int knopka5 = 7; int knopka6 = 8; void setup() { analogReference(DEFAULT); Serial.begin(9600); pinMode(knopka1, INPUT); digitalWrite(knopka1, HIGH); pinMode(knopka2, INPUT); digitalWrite(knopka2, HIGH); pinMode(knopka3, INPUT); digitalWrite(knopka3, HIGH); pinMode(knopka4, INPUT); digitalWrite(knopka4, HIGH); pinMode(knopka5, INPUT); digitalWrite(knopka5, HIGH); pinMode(knopka6, INPUT); digitalWrite(knopka6, HIGH); } void loop() { Serial.write('a'); Serial.write(map(analogRead(pot1x), 0, 1023, 0, 254)); Serial.write('b'); Serial.write(map(analogRead(pot1y), 0, 1023, 0, 127)); Serial.write('c'); Serial.write(map(analogRead(pot2x), 0, 1023, 0, 127)); Serial.write('d'); Serial.write(digitalRead(knopka1)); //кнопка 1 Serial.write('e'); Serial.write(digitalRead(knopka2)); //кнопка 2 Serial.write('f'); Serial.write(digitalRead(knopka3)); //... Serial.write('g'); Serial.write(digitalRead(knopka4)); Serial.write('h'); Serial.write(digitalRead(knopka5)); Serial.write('i'); Serial.write(digitalRead(knopka6)); Serial.write('j'); Serial.write(map(analogRead(ff), 0, 1023, 0, 1)); Serial.write('k'); Serial.write(map(analogRead(fw), 0, 1023, 0, 1)); delay(50); }Понятнее если
Понятнее если
Я многого еще не знаю и я копипастил))
Видимо не осилили про асинхронность UART, про передачу байтами, про протокол? ;)
Передатчик может запутать приемник (в том виде как сейчас ревлизован приемник) этими пересылками:
45Serial.write(map(analogRead(pot1x), 0, 1023, 0, 254));47Serial.write(map(analogRead(pot1y), 0, 1023, 0, 127));49Serial.write(map(analogRead(pot2x), 0, 1023, 0, 127));т.к. функция map() может вернуть значение = вашим передаваемым символам: от 'a' до 'k', ведь символ это тоже байт! А учитывая асинхронность передачи/приема данных, ваша реализация приемника не гарантирует правильный прием (разберем на одном примере с 'a'):
045if(Serial.available() &&Serial.read() =='a')046{047a =Serial.read();048//analogWrite(speedl,a);049//analogWrite(speedr,a);050}Допустим, ваш передатчик передал символ 'a', а потом передал -
Serial.write(map(analogRead(pot1x), 0, 1023, 0, 254)); ,но map() вернул число = значению символа 'a'. Таким образом передатчик передал 2 символа 'a'. Тепрь рассмотрим код приемника, допустим(!) цикл попал на первое чнеие символа 'a' сработало условие и мы сразу читаем втрой байт... А кто вам сказал, что второй байт в это мгновение уже поступил в приемник и готов быть счтитан!? - это и есть следствие асинхронности приема/передачи UART! Следовательно переменной a будет присвоена -1 (если я не путаю) - уже ошибка в данных! Далее цикл пролетел несколько оборотов, в приемник наконец потсупил второй символ 'a' от передатчика и мы опять провалились на присвоение значения переменной a - вторая ошибка в принятых данных (тут может либо -1, если следующий байт еще не поступил в приемник или непонятно какой байт следующей команды передатчика (ваши символы от 'a' до 'k' )).
Аналогичные проблемы вас поджидают и с командами 'b' и 'c'.
Такой пример понятен? Надеюсь с асинхронностю покончили. А то что у вас все заработало правильно, так это звезды так сложились или арду вам подарок приготовила к празднику:)
(шепотом: не хотел бы я быть в одной команде с таким танком, еще пальнет в своих :)
Я не волшебник, я только учусь. Поиграться пока хватает)) Сейчас пытаюсь сделать компенсацию дула и вот тут засада... Может кто-нибудь скачать отсюда https://www.loveelectronics.co.uk/Tutorials/13/tilt-compensated-compass-arduino-tutorial библиотеки и выложить сюда? Не могу зайти туда(((
Я тоже вчера не смог, плюс Хром перехватил перенаправление на другой вредоносный сайт. А раньше я на это сайт заходил и эту статью читал. Гляну, может сохранилась копия.
Я нашел библиотеки эти, но..
tiltcompass:74: error: request for member 'YAxis' in 'acc', which is of non-class type 'int'
Итак практически на каждую строку.
А я нашел библиотеку для пересылки данных - EasyTransfer! Попробуйте использовать ее в своих тестах, похоже она использует те фичи, которые я пытался популярно объяснить.
У меня в примерах она есть. Надо посмотреть. Там и для virtualWire есть примеры, а у меня как раз такие трансиверы завалялись))