#1 2024-03-31 09:32:15

wsx
Учасник
Зареєстрований: 2024-03-31
Повідомлень: 14

Допоможіть будь ласка початківцю.

Доброго дня, Шановні. Я ну прям дуже початківець, допоможіть будь ласка розібратися.
Задача в мене така: одна ардуінка працює як пульт, зчитує джойстик; друга керує двома сервоприводами; зв'язок між ними по 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)

Неактивний

#2 2024-03-31 10:29:03

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 205

Re: Допоможіть будь ласка початківцю.

Неактивний

#3 2024-03-31 10:35:09

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 205

Re: Допоможіть будь ласка початківцю.

А це:

Serial.write(buff[2]);

спроба доступа за межі масива buff. Це невизначена поведінка.
Почитайте основи про масиви в C (у C++ також використовуються C-шні масиви).

Неактивний

#4 2024-03-31 10:57:48

wsx
Учасник
Зареєстрований: 2024-03-31
Повідомлень: 14

Re: Допоможіть будь ласка початківцю.

dimich пише:

Одразу так і робив, але не компілюється і все...
Така помилка:   Compilation error: no matching function for call to 'HardwareSerial::readBytes(int [2], int)'

Остання редакція wsx (2024-03-31 11:09:59)

Неактивний

#5 2024-03-31 11:00:23

wsx
Учасник
Зареєстрований: 2024-03-31
Повідомлень: 14

Re: Допоможіть будь ласка початківцю.

dimich пише:

А це:

Serial.write(buff[2]);

спроба доступа за межі масива buff. Це невизначена поведінка.
Почитайте основи про масиви в C (у C++ також використовуються C-шні масиви).

По книжці  Serial.write(buf, len)   , але так не компілюється
Serial.write(buff[2]);   так пройшло, але мабуть це не вірно...
Читав вже перечитав, мозок пухне, не хоче компілювати... Тому і звернувся по допомогу.

Остання редакція wsx (2024-03-31 11:14:29)

Неактивний

#6 2024-03-31 11:34:02

просто зайшов
Гість

Re: Допоможіть будь ласка початківцю.

wsx пише:

Одразу так і робив, але не компілюється і все...
Така помилка:   Compilation error: no matching function for call to 'HardwareSerial::readBytes(int [2], int)'

естественно не компилируется...
функция ожидает размерность Byte 8бит , а вы ей буфер размерностью 16бит подсовываете еще и знаковый.

#7 2024-03-31 11:35:36

просто зайшов
Гість

Re: Допоможіть будь ласка початківцю.

buffer: the buffer to store the bytes in. Allowed data types: array of char or byte.

#8 2024-03-31 11:45:40

wsx
Учасник
Зареєстрований: 2024-03-31
Повідомлень: 14

Re: Допоможіть будь ласка початківцю.

Щось я заплутався.. Отже масив з бітів, а не з байтів? який тоді від нього сенс? Один байт можно і так відправити - отримати
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)

Неактивний

#9 2024-03-31 12:13:03

просто зайшов
Гість

Re: Допоможіть будь ласка початківцю.

wsx пише:

. Як це зробити?
По одному ж не можна відправляти, приймач не зрозуміє хто є хто..

Свои переменные преобразовать в строку,
Передать: 0х55,0хАА (признак начала посылки) , "строка первой переменой", "строка второй переменой, 0х0D(символ "возврат коретки"окончание посылки)
На приемнике получив символ 0х0D ожидать признак начала посылки 0х55,0хАА, если получен принимать строковые переменные.
Строковые переменные преобразовать в числа.

#10 2024-03-31 12:30:06

wsx
Учасник
Зареєстрований: 2024-03-31
Повідомлень: 14

Re: Допоможіть будь ласка початківцю.

Дякую за допомогу, але нічого не зрозумів... буду намагатись. Якось простіше ніяк неможна?
Та чому всеж таки не працює  Serial.write(buf, len)  і  Serial.readBytes(buffer, length)   ?   ну повинно ж передавати декілька байтів по опису...

Неактивний

#11 2024-03-31 12:48:50

wsx
Учасник
Зареєстрований: 2024-03-31
Повідомлень: 14

Re: Допоможіть будь ласка початківцю.

схоже помилка була така
не   int buff[2];
а     byte buff[2];
скомпілювало, один серво працює. підключу другий.

Неактивний

#12 2024-03-31 13:01:07

просто зайшов
Гість

Re: Допоможіть будь ласка початківцю.

wsx пише:

Та чому всеж таки не працює  Serial.write(buf, len)  і  Serial.readBytes(buffer, length)   ?   ну повинно ж передавати декілька байтів по опису...

Потому что тип данных не совпадает. Вы массив  buff[2] определии как тип  int ,
функция принимает тип byte , выше специально привел сноску с описания функции и выделил цветом требуемый тип.
Откройте любой учебник по Си и прочитайте, что такое типы данных, и чем отличается тип byte от int .

wsx пише:

Дякую за допомогу, але нічого не зрозумів... буду намагатись. Якось простіше ніяк неможна?

Можно сложнее, простише вряд ли.
Преобразование чисел в строку http://we.easyelectronics.ru/Soft/preobrazuem-v-stroku-chast-1-celye-chisla.html

#13 2024-03-31 13:10:35

wsx
Учасник
Зареєстрований: 2024-03-31
Повідомлень: 14

Re: Допоможіть будь ласка початківцю.

Так ось і є простіше. Підключив - все працює.
Робочий скетч, передавач:

#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);}
}

smile  smile  smile

Неактивний

#14 2024-03-31 13:11:35

просто зайшов
Гість

Re: Допоможіть будь ласка початківцю.

wsx пише:

скомпілювало, один серво працює. підключу другий.

а как Вы будете различать где в посылке байты для первой сервы, а где для второй?

#15 2024-03-31 13:16:45

wsx
Учасник
Зареєстрований: 2024-03-31
Повідомлень: 14

Re: Допоможіть будь ласка початківцю.

просто зайшов пише:

Потому что тип данных не совпадает. Вы массив  buff[2] определии как тип  int ,
функция принимает тип byte , выше специально привел сноску с описания функции и выделил цветом требуемый тип.
Откройте любой учебник по Си и прочитайте, что такое типы данных, и чем отличается тип byte от int .

Та вот читав - недочитав... мозок закипів, починаючий...
хотілось щоб носом ткнули.. але й так допомогло.
Дякую!

Неактивний

#16 2024-03-31 13:18:19

wsx
Учасник
Зареєстрований: 2024-03-31
Повідомлень: 14

Re: Допоможіть будь ласка початківцю.

просто зайшов пише:
wsx пише:

скомпілювало, один серво працює. підключу другий.

а как Вы будете различать где в посылке байты для первой сервы, а где для второй?

Ну ось так
valud=buff[0];
  vallr=buff[1];
Може теж щось невірно? але воно працює

Неактивний

#17 2024-03-31 13:23:12

просто зайшов
Гість

Re: Допоможіть будь ласка початківцю.

wsx пише:

Так ось і є простіше. Підключив - все працює.
Робочий скетч, передавач:
smile  smile  smile

Это не рабочие решение.
Это работает только до тех пор пока индекс буффера передачи совпадает с индексом буфера приемника
Включите/выключите пару раз дурину на  приемной стороне  и Вы очень быстро получите ситуацию когда приемник будет принимать первым байтом buff[1] ,а вторым buff[1]

#18 2024-03-31 13:24:33

просто зайшов
Гість

Re: Допоможіть будь ласка початківцю.

просто зайшов пише:

первым байтом buff[1] ,а вторым buff[1]

первым байтом buff[1] ,а вторым buff[0] !!!!!

#19 2024-03-31 13:31:25

wsx
Учасник
Зареєстрований: 2024-03-31
Повідомлень: 14

Re: Допоможіть будь ласка початківцю.

просто зайшов пише:
wsx пише:

Так ось і є простіше. Підключив - все працює.
Робочий скетч, передавач:
smile  smile  smile

Это не рабочие решение.
Это работает только до тех пор пока индекс буффера передачи совпадает с индексом буфера приемника
Включите/выключите пару раз дурину на  приемной стороне  и Вы очень быстро получите ситуацию когда приемник будет принимать первым байтом buff[1] ,а вторым buff[1]

Спробував пару десятків разів, покищо не було такого...
Але ж і передавач задає порядок:
buff[0]=valud;
  buff[1]=vallr;
  Serial.write(buff,2);
буду мати на увазі, але поки все ок!

Неактивний

#20 2024-03-31 13:34:43

просто зайшов
Гість

Re: Допоможіть будь ласка початківцю.

wsx пише:

буду мати на увазі, але поки все ок!

Каждый должен наступить свои детские грабли  smile

#21 2024-03-31 13:45:58

wsx
Учасник
Зареєстрований: 2024-03-31
Повідомлень: 14

Re: Допоможіть будь ласка початківцю.

Вже наступив smile
Один раз таке трапилось sad
Виходить тільки це мені допоможе?:

Свои переменные преобразовать в строку,
Передать: 0х55,0хАА (признак начала посылки) , "строка первой переменой", "строка второй переменой, 0х0D(символ "возврат коретки"окончание посылки)
На приемнике получив символ 0х0D ожидать признак начала посылки 0х55,0хАА, если получен принимать строковые переменные.
Строковые переменные преобразовать в числа.

Можно хоч трохи вразуміліше, як для початківця?

Неактивний

#22 2024-03-31 14:00:16

wsx
Учасник
Зареєстрований: 2024-03-31
Повідомлень: 14

Re: Допоможіть будь ласка початківцю.

Або якщо просто додати в масив якийсь перший байт та останній, які не співпадають з основними. А в приймачеві розділити по байтах та брати інформаційні після першого "кодового" і останній для перевірки.
Так проканає?

Неактивний

#23 2024-03-31 15:56:10

просто зайшов
Гість

Re: Допоможіть будь ласка початківцю.

wsx пише:

Можно хоч трохи вразуміліше, як для початківця?

можно
байт имеет размерность 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');

#24 2024-03-31 16:15:13

wsx
Учасник
Зареєстрований: 2024-03-31
Повідомлень: 14

Re: Допоможіть будь ласка початківцю.

Дякую, буду "вкурювать"...

Неактивний

#25 2024-03-31 18:57:58

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 205

Re: Допоможіть будь ласка початківцю.

wsx пише:

Або якщо просто додати в масив якийсь перший байт та останній, які не співпадають з основними. А в приймачеві розділити по байтах та брати інформаційні після першого "кодового" і останній для перевірки.
Так проканає?

Serial передає потік даних (stream), сам по собі він безперервний. Ви хочете передавати датаграми, тобто окремі посилки з початком і кінцем.
Є два основних метода:

1. Відокремлювати початок посилки по часу. На передавачі слати дані з певною затримкою між датаграмами (у вас уже є пауза 50 мс). На приймачі, якщо даних не було довше певного періоду, вважати нові дані початком посилки.

2. Відокремлювати початок (та/або кінець) посилки певним маркером. На приймачі сканувати потік на наявність цього маркера. Майте на увазі, що у загальному випадку всередині датаграми також можуть зустрітись дані, які співпадають зі значенням маркера. Щоб уникнути хибної синхронізації бажано додати контрольну суму, хоча б CRC8. При неспівпадінні контрольної суми або маркера кінця посилки не відкидати всі данні, що надійшли, а продовжити сканування з наступного символа після маркера. Правильне рішення цієї задачі не таке просте, як здається на перший погляд.

Кожен метод має свої переваги і недоліки. Можна використовувати і обидва методи одночасно.

Неактивний

Швидке повідомлення

Введіть повідомлення і натисніть Надіслати

Підвал форуму