Ви не увійшли.
Доброго дня, Шановні. Я ну прям дуже початківець, допоможіть будь ласка розібратися.
Задача в мене така: одна ардуінка працює як пульт, зчитує джойстик; друга керує двома сервоприводами; зв'язок між ними по UART.
Один байт передавати навчився, але мені потрібно як мінімум 2 (потім більше). Підкажіть, як коректно передавати та приймати масив, зайшов в тупік, приймач не компілюється ні в яких варіантах...
передавач, скомпілювався, але чи вірно Serial.write(buff[2]);
#include <SoftwareSerial.h>
int valud;
int vallr;
int buff[2];
int potpinud=0;
int potpinlr=1;
void setup()
{
Serial.begin(9600,SERIAL_8N1);
pinMode(potpinud,INPUT);
pinMode(potpinlr,INPUT);
}
void loop()
{
valud=analogRead(potpinud);
vallr=analogRead(potpinlr);
valud=map(valud,0,1023,1,180);
vallr=map(vallr,0,1023,1,180);
buff[0]=valud;
buff[1]=vallr;
Serial.write(buff[2]);
delay(20);
}
приймач:
#include <SoftwareSerial.h>
#include <Servo.h>
Servo servoud;
Servo servolr;
int valud;
int vallr;
int buff[2]={0,0};
void setup()
{
Serial.begin(9600,SERIAL_8N1);
servoud.attach(6);
servolr.attach(5);
}
void loop(){
buff=Serial.readBytes();
valud=buff[0];
vallr=buff[1];
if (valud>0) {
valud=valud-1;
servoud.write(valud);}
if (vallr>0) {
vallr=vallr-1;
servolr.write(vallr);}
delay(20);
}
Ніяк не компілює buff=Serial.readBytes();
Остання редакція wsx (2024-03-31 11:10:51)
Неактивний
https://www.arduino.cc/reference/en/lan … readbytes/:
Serial.readBytes(buffer, length)
Неактивний
https://www.arduino.cc/reference/en/lan … readbytes/:
Serial.readBytes(buffer, length)
Одразу так і робив, але не компілюється і все...
Така помилка: Compilation error: no matching function for call to 'HardwareSerial::readBytes(int [2], int)'
Остання редакція wsx (2024-03-31 11:09:59)
Неактивний
А це:
Serial.write(buff[2]);
спроба доступа за межі масива buff. Це невизначена поведінка.
Почитайте основи про масиви в C (у C++ також використовуються C-шні масиви).
По книжці Serial.write(buf, len) , але так не компілюється
Serial.write(buff[2]); так пройшло, але мабуть це не вірно...
Читав вже перечитав, мозок пухне, не хоче компілювати... Тому і звернувся по допомогу.
Остання редакція wsx (2024-03-31 11:14:29)
Неактивний
Одразу так і робив, але не компілюється і все...
Така помилка: Compilation error: no matching function for call to 'HardwareSerial::readBytes(int [2], int)'
естественно не компилируется...
функция ожидает размерность Byte 8бит , а вы ей буфер размерностью 16бит подсовываете еще и знаковый.
buffer: the buffer to store the bytes in. Allowed data types: array of char or byte.
Щось я заплутався.. Отже масив з бітів, а не з байтів? який тоді від нього сенс? Один байт можно і так відправити - отримати
Serial.write(val);
val=Serial.read();
Так все працює добре на один серво. Але мені потрібно два байти відправити (а потім ще більше). Як це зробити?
По одному ж не можна відправляти, приймач не зрозуміє хто є хто..
Ну ось же, байт.. або я щось недогоняю?
Serial.write(val), Serial.write(buf, len)
Отправляет в порт val численное значение или строку, или отправляет количество len байт из буфера buf.
Serial.readBytes(buffer, length)
Читает данные из порта и закидывает их в буфер buffer . Также указывается количество байт, который нужно записать – length (чтобы не переполнить буфер).
Остання редакція wsx (2024-03-31 12:11:55)
Неактивний
. Як це зробити?
По одному ж не можна відправляти, приймач не зрозуміє хто є хто..
Свои переменные преобразовать в строку,
Передать: 0х55,0хАА (признак начала посылки) , "строка первой переменой", "строка второй переменой, 0х0D(символ "возврат коретки"окончание посылки)
На приемнике получив символ 0х0D ожидать признак начала посылки 0х55,0хАА, если получен принимать строковые переменные.
Строковые переменные преобразовать в числа.
Дякую за допомогу, але нічого не зрозумів... буду намагатись. Якось простіше ніяк неможна?
Та чому всеж таки не працює Serial.write(buf, len) і Serial.readBytes(buffer, length) ? ну повинно ж передавати декілька байтів по опису...
Неактивний
Та чому всеж таки не працює Serial.write(buf, len) і Serial.readBytes(buffer, length) ? ну повинно ж передавати декілька байтів по опису...
Потому что тип данных не совпадает. Вы массив buff[2] определии как тип int ,
функция принимает тип byte , выше специально привел сноску с описания функции и выделил цветом требуемый тип.
Откройте любой учебник по Си и прочитайте, что такое типы данных, и чем отличается тип byte от int .
Дякую за допомогу, але нічого не зрозумів... буду намагатись. Якось простіше ніяк неможна?
Можно сложнее, простише вряд ли.
Преобразование чисел в строку http://we.easyelectronics.ru/Soft/preobrazuem-v-stroku-chast-1-celye-chisla.html
Так ось і є простіше. Підключив - все працює.
Робочий скетч, передавач:
#include <SoftwareSerial.h>
int valud;
int vallr;
byte buff[2];
int potpinud=0;
int potpinlr=1;
void setup()
{
Serial.begin(9600,SERIAL_8N1);
pinMode(potpinud,INPUT);
pinMode(potpinlr,INPUT);
}
void loop()
{
valud=analogRead(potpinud);
vallr=analogRead(potpinlr);
valud=map(valud,0,1023,1,180);
vallr=map(vallr,0,1023,1,180);
buff[0]=valud;
buff[1]=vallr;
Serial.write(buff,2);
delay(50);
}
приймач:
#include <SoftwareSerial.h>
#include <Servo.h>
Servo servoud;
Servo servolr;
int valud;
int vallr;
byte buff[2];
void setup()
{
Serial.begin(9600,SERIAL_8N1);
servoud.attach(6);
servolr.attach(5);
}
void loop(){
Serial.readBytes(buff,2);
valud=buff[0];
vallr=buff[1];
if (valud>0) {
valud=valud-1;
servoud.write(valud);
delay(20);}
if (vallr>0) {
vallr=vallr-1;
servolr.write(vallr);
delay(20);}
}
Неактивний
скомпілювало, один серво працює. підключу другий.
а как Вы будете различать где в посылке байты для первой сервы, а где для второй?
Потому что тип данных не совпадает. Вы массив buff[2] определии как тип int ,
функция принимает тип byte , выше специально привел сноску с описания функции и выделил цветом требуемый тип.
Откройте любой учебник по Си и прочитайте, что такое типы данных, и чем отличается тип byte от int .
Та вот читав - недочитав... мозок закипів, починаючий...
хотілось щоб носом ткнули.. але й так допомогло.
Дякую!
Неактивний
wsx пише:скомпілювало, один серво працює. підключу другий.
а как Вы будете различать где в посылке байты для первой сервы, а где для второй?
Ну ось так
valud=buff[0];
vallr=buff[1];
Може теж щось невірно? але воно працює
Неактивний
Так ось і є простіше. Підключив - все працює.
Робочий скетч, передавач:
Это не рабочие решение.
Это работает только до тех пор пока индекс буффера передачи совпадает с индексом буфера приемника
Включите/выключите пару раз дурину на приемной стороне и Вы очень быстро получите ситуацию когда приемник будет принимать первым байтом buff[1] ,а вторым buff[1]
первым байтом buff[1] ,а вторым buff[1]
первым байтом buff[1] ,а вторым buff[0] !!!!!
wsx пише:Так ось і є простіше. Підключив - все працює.
Робочий скетч, передавач:
Это не рабочие решение.
Это работает только до тех пор пока индекс буффера передачи совпадает с индексом буфера приемника
Включите/выключите пару раз дурину на приемной стороне и Вы очень быстро получите ситуацию когда приемник будет принимать первым байтом buff[1] ,а вторым buff[1]
Спробував пару десятків разів, покищо не було такого...
Але ж і передавач задає порядок:
buff[0]=valud;
buff[1]=vallr;
Serial.write(buff,2);
буду мати на увазі, але поки все ок!
Неактивний
буду мати на увазі, але поки все ок!
Каждый должен наступить свои детские грабли
Вже наступив
Один раз таке трапилось
Виходить тільки це мені допоможе?:
Свои переменные преобразовать в строку,
Передать: 0х55,0хАА (признак начала посылки) , "строка первой переменой", "строка второй переменой, 0х0D(символ "возврат коретки"окончание посылки)
На приемнике получив символ 0х0D ожидать признак начала посылки 0х55,0хАА, если получен принимать строковые переменные.
Строковые переменные преобразовать в числа.
Можно хоч трохи вразуміліше, як для початківця?
Неактивний
Або якщо просто додати в масив якийсь перший байт та останній, які не співпадають з основними. А в приймачеві розділити по байтах та брати інформаційні після першого "кодового" і останній для перевірки.
Так проканає?
Неактивний
Можно хоч трохи вразуміліше, як для початківця?
можно
байт имеет размерность 8 бит и принимает значения от 0 до 255 или 0x00..0xFF
каждому значению в таблице ASCII соответствует свой символ char
Обычно начало посылки начинают с кодов 0x55 & 0xAA
(в двоичном коде это инверсные последовательности нулей и едениц, 0x55=0b01010101, 0xAA=0b10101010
и при передаче по длинным линиям в коде Грея или по радиоканалу по нем проводят синхронизацию приемника ЮАРТ.)
Чтобы передаваемые данные не совпадали с кодами начала посылки их передают десятичными цифрами ASCII-кодов 0..9 >> 0x30..0x39 ( первая тетрада битов последовательность 0011 , вторая двоичный код цифр)
конец посылки отмечаем или передачей спец.символа Carriage return= 0x0D (возврат коретки) или контрольной суммой.
пример:
byte buff[10];
//две переменных
byte var1=85;
byte var2=170;
//собираем пакет для передачи
buff[0]=0x55; //коды начала
buff[1]=0xAA; //посылки
//переводим числа в строку:
buff[2]=var1/100 + '0'; //сотни
buff[3]=(var1%100)/10 + '0' ; //десятки
buff[4]=var1%10 + '0'; //единицы
buff[5]=var2/100 + '0'; //сотни
buff[6]=(var2%100)/10 + '0'; //десятки
buff[7]=var2%10 + '0'; //единицы
buff[8]=0x0D;// конец посылки
buff[9]=0x00;// NULL признак конца строки.
восстановление переменных на стороне приемника
var1 = (buff[2]-'0')*100 + (buff[3]-'0')*10 + (buff[4]-'0');
var2 = (buff[5]-'0')*100 + (buff[6]-'0')*10 + (buff[7]-'0');
Або якщо просто додати в масив якийсь перший байт та останній, які не співпадають з основними. А в приймачеві розділити по байтах та брати інформаційні після першого "кодового" і останній для перевірки.
Так проканає?
Serial передає потік даних (stream), сам по собі він безперервний. Ви хочете передавати датаграми, тобто окремі посилки з початком і кінцем.
Є два основних метода:
1. Відокремлювати початок посилки по часу. На передавачі слати дані з певною затримкою між датаграмами (у вас уже є пауза 50 мс). На приймачі, якщо даних не було довше певного періоду, вважати нові дані початком посилки.
2. Відокремлювати початок (та/або кінець) посилки певним маркером. На приймачі сканувати потік на наявність цього маркера. Майте на увазі, що у загальному випадку всередині датаграми також можуть зустрітись дані, які співпадають зі значенням маркера. Щоб уникнути хибної синхронізації бажано додати контрольну суму, хоча б CRC8. При неспівпадінні контрольної суми або маркера кінця посилки не відкидати всі данні, що надійшли, а продовжити сканування з наступного символа після маркера. Правильне рішення цієї задачі не таке просте, як здається на перший погляд.
Кожен метод має свої переваги і недоліки. Можна використовувати і обидва методи одночасно.
Неактивний