EasyTransfer + String

ProstoAlex
Offline
Зарегистрирован: 21.01.2015

Коллеги, прошу помощи. Моих отрывчатых знаний не хватает, чтобы победить С++ ))

итак, есть 2 меги, соединенных через i2c с помощью либы easytransfer

образец либы:

Мастер:

#include <Wire.h>
#include <EasyTransferI2C.h>

//create object
EasyTransferI2C ET; 

struct RECEIVE_DATA_STRUCTURE{
  //put your variable definitions here for the data you want to receive
  //THIS MUST BE EXACTLY THE SAME ON THE OTHER ARDUINO
  int16_t blinks;
  int16_t pause;
};

//give a name to the group of data
RECEIVE_DATA_STRUCTURE mydata;

//define slave i2c address
#define I2C_SLAVE_ADDRESS 9

void setup(){
  Wire.begin(I2C_SLAVE_ADDRESS);
  //start the library, pass in the data details and the name of the serial port. Can be Serial, Serial1, Serial2, etc. 
  ET.begin(details(mydata), &Wire);
  //define handler function on receiving data
  Wire.onReceive(receive);
  
  pinMode(13, OUTPUT);
  
}

void loop() {
  //check and see if a data packet has come in. 
  if(ET.receiveData()){
    //this is how you access the variables. [name of the group].[variable name]
    //since we have data, we will blink it out. 
    for(int i = mydata.blinks; i>0; i--){
      digitalWrite(13, HIGH);
      delay(mydata.pause * 100);
      digitalWrite(13, LOW);
      delay(mydata.pause * 100);
    }
  }
}

void receive(int numBytes) {}

Slave:

#include <Wire.h>
#include <EasyTransferI2C.h>

//create object
EasyTransferI2C ET; 

struct SEND_DATA_STRUCTURE{
  //put your variable definitions here for the data you want to send
  //THIS MUST BE EXACTLY THE SAME ON THE OTHER ARDUINO
  int16_t blinks;
  int16_t pause;
};

//give a name to the group of data
SEND_DATA_STRUCTURE mydata;

//define slave i2c address
#define I2C_SLAVE_ADDRESS 9

void setup(){
  Wire.begin();
  //start the library, pass in the data details and the name of the serial port. Can be Serial, Serial1, Serial2, etc.
  ET.begin(details(mydata), &Wire);
  
  pinMode(13, OUTPUT);
  
  randomSeed(analogRead(0));
  
}

void loop(){
  //this is how you access the variables. [name of the group].[variable name]
  mydata.blinks = random(5);
  mydata.pause = random(5);
  //send the data
  ET.sendData(I2C_SLAVE_ADDRESS);
  
  //Just for fun, we will blink it out too
   for(int i = mydata.blinks; i>0; i--){
      digitalWrite(13, HIGH);
      delay(mydata.pause * 100);
      digitalWrite(13, LOW);
      delay(mydata.pause * 100);
    }
  
  delay(5000);
}

В примерах передаются данные int16_t.

А мне надо - string.

И как я только не изгалялся, чтобы перевести String в Char или byte - ни в какую...

#include <Wire.h>
#include <EasyTransferI2C.h>

//create object
EasyTransferI2C ET; 
  String sss="abcdef";

struct SEND_DATA_STRUCTURE{
  //put your variable definitions here for the data you want to send
  //THIS MUST BE EXACTLY THE SAME ON THE OTHER ARDUINO
  int16_t blinks;
  int16_t pause;
   char ss[7];
};

//give a name to the group of data
SEND_DATA_STRUCTURE mydata;

//define slave i2c address
#define I2C_SLAVE_ADDRESS 9

void setup(){
  Wire.begin();
  Serial.begin(115200);
  //start the library, pass in the data details and the name of the serial port. Can be Serial, Serial1, Serial2, etc.
  ET.begin(details(mydata), &Wire);
  
  pinMode(13, OUTPUT);
  
  randomSeed(analogRead(0));
  
}

void loop(){
  //this is how you access the variables. [name of the group].[variable name]
  mydata.blinks = random(5);
  mydata.pause = random(5);

 for (byte i = 0; i <= sss.length()+1; i++) {
  mydata.ss[i] = sss.substring(i,i+1).c_str();
  Serial.print("char i=");Serial.println(mydata.ss[i]);
 }

      

 Serial.print("mydata.ss[6]=");Serial.println(mydata.ss);
  Serial.print("mydata.pause=");Serial.println(mydata.pause);
 

   //send the data
  ET.sendData(I2C_SLAVE_ADDRESS);
  
  //Just for fun, we will blink it out too
   for(int i = mydata.blinks; i>0; i--){
      digitalWrite(13, HIGH);
      delay(mydata.pause * 100);
      digitalWrite(13, LOW);
      delay(mydata.pause * 100);
    }
  
  delay(500);
}

 Может, подскажет кто?

явно что-то элементарное, чего я в упор не вижу...

b707
Offline
Зарегистрирован: 26.05.2017

зачем заводить String. чтобы потом мучаться и переводить ее в char? Что мешает сразу обьявить sss как

char sss[] = "abcdef";

 

 

anarch
Offline
Зарегистрирован: 10.09.2017
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ProstoAlex пишет:

И как я только не изгалялся, чтобы перевести String в Char или byte - ни в какую...

Боюсь даже представить, как Вы это делали. Только зачем её переводить, если у String есть готовый метод

const char * c_str()

который благополучно возвращает её буфер как char * ? Пользуйтесь на здоровье.

anarch
Offline
Зарегистрирован: 10.09.2017

ЕвгенийП пишет:

Боюсь даже представить, как Вы это делали. Только зачем её переводить, если у String есть готовый метод

const char * c_str()

который благополучно возвращает её буфер как char * ? Пользуйтесь на здоровье.

for (byte i = 0; i <= sss.length()+1; i++) {
  mydata.ss[i] = sss.substring(i,i+1).c_str();
  Serial.print("char i=");Serial.println(mydata.ss[i]);
 }

Так вот же ТС пытался. 

с_str() возращает const char* и отправив ее в структуру ой боюсь компилятор заругает.

По ссылке выше приведенной описан этот случай.

strcpy(mydata.ss,sss.c_str());
Serial.println(mydata.ss);

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

anarch пишет:

Так вот же ТС пытался. 

Это не ТС пытался, а пример из библиотеки, который сопипасщен, но не понят. ТС же 

ProstoAlex пишет:

И как я только не изгалялся, чтобы перевести String в Char или byte - ни в какую...

ProstoAlex
Offline
Зарегистрирован: 21.01.2015

спасибо всем откликнувшимся!

пока получается так:

  char sss[7] = "abcdef";

struct SEND_DATA_STRUCTURE{
  int16_t blinks;

   char ss;
};


void loop(){
  mydata.blinks = random(5);
  mydata.ss = sss;
      
 Serial.print("char i="); Serial.println(sss);
 Serial.print("mydata.ss[]=");Serial.println(mydata.ss);
  Serial.print("mydata.blinks=");Serial.println(mydata.blinks);
 
  ET.sendData(I2C_SLAVE_ADDRESS);
}

получается так:

-> char i=abcdef
-> mydata.ss[]=
-> mydata.blinks=3

Соответственно, на вторую ардуино ничего не передается.

Подскажите, как правильно присвоить mydata.ss = sss ?

b707
Offline
Зарегистрирован: 26.05.2017

вы экземпляр структуры mydata вообще не создаете? Метод detais() не вызываете? Или это вы просто скетч "сократили"?

выкладывайте все, чтобы не нужно было догадываться, что вы забыли по незнанию, а что "сократили", потому что думали не засорять форум

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ProstoAlex пишет:

Подскажите, как правильно присвоить mydata.ss = sss ?

Никак. Они разных типов и разного размера.

Нельзя переменную размеров в 7 байтов впихнуть в переменную размером в 1 байт.

b707
Offline
Зарегистрирован: 26.05.2017

ProstoAlex пишет:

Подскажите, как правильно присвоить mydata.ss = sss ?

а ответы выше чуть внимательнее прочитать? в ветке всего 7 сообщений. считая ваши.

ProstoAlex
Offline
Зарегистрирован: 21.01.2015

b707 пишет:

речь про strcpy(mydata.ss,sss.c_str()); ?

ProstoAlex
Offline
Зарегистрирован: 21.01.2015

ЕвгенийП пишет:

Евгений, тогда более общий вопрос - как String (массив char) передать по easytransfer?

ведь наверняка задача на 2 минуты... )

ProstoAlex
Offline
Зарегистрирован: 21.01.2015


[quote=b707]

#include <Wire.h>
#include <EasyTransferI2C.h>

//create object
EasyTransferI2C ET; 
  char sss[7] = "abcdef";

struct SEND_DATA_STRUCTURE{
  int16_t blinks;

   char ss;
};

//give a name to the group of data
SEND_DATA_STRUCTURE mydata;

//define slave i2c address
#define I2C_SLAVE_ADDRESS 9

void setup(){
  Wire.begin();
  Serial.begin(115200);
  //start the library, pass in the data details and the name of the serial port. Can be Serial, Serial1, Serial2, etc.
  ET.begin(details(mydata), &Wire);
  
  pinMode(13, OUTPUT);
  
  randomSeed(analogRead(0));
  }

void loop(){
  //this is how you access the variables. [name of the group].[variable name]
  mydata.blinks = random(5);
  mydata.ss = sss;

 Serial.print("char i="); Serial.println(sss);
 Serial.print("mydata.ss[]=");Serial.println(mydata.ss);
  Serial.print("mydata.blinks=");Serial.println(mydata.blinks);
 
  ET.sendData(I2C_SLAVE_ADDRESS);

  delay(500);
}

 

 

b707
Offline
Зарегистрирован: 26.05.2017

ProstoAlex пишет:

речь про strcpy(mydata.ss,sss.c_str()); ?

да, я имел в виду это - но у вас не сработает, я просто не заметил всех ваших косяков. Читайте ответ Евгения

 

b707
Offline
Зарегистрирован: 26.05.2017

ProstoAlex пишет:

Евгений, тогда более общий вопрос - как String (массив char) передать по easytransfer?

ведь наверняка задача на 2 минуты... )

даже на одну. Превратить String в char* и передать.

А как передать непосредственно String - я не знаю. Может это и невозможно...

ProstoAlex
Offline
Зарегистрирован: 21.01.2015

прям беда...

где-то видел (сейчас найти уже не могу), что этой либой можно переносить bytes, floats, int, но не стринг

а мне надо через i2c передать bytes, floats, int и string...

родная #wire вообще кроме байтов ничего не передает...

неужели единственный способ - конвертить string (char) в bytes, и их уже передавать?

sadman41
Offline
Зарегистрирован: 19.10.2016

А эти Ваши floats, int и что-то там ещё - не байты?

ProstoAlex
Offline
Зарегистрирован: 21.01.2015

ну, в основе всего bytes...

b707
Offline
Зарегистрирован: 26.05.2017

ProstoAlex пишет:

ну, в основе всего bytes...

я вам больше скажу - char и byte - это грубо говоря одно и тоже

ПростоАлекс - судя по дискуссии, вы пока не готовы передавать string по wire. Вам нужно сесть и прочитать, что такое традиционные строки языка Си. Не эти навороченные ардуиновские String. а то что называется массивами символов

И тогда вы легко исправите ошибки в коде у вас все получится

ProstoAlex
Offline
Зарегистрирован: 21.01.2015

я, конечно, ожидал готовый работающий код на блюдечке, но спасибо большое - пойду копать в сторону массивов ! )))

anarch
Offline
Зарегистрирован: 10.09.2017

b707 пишет:

ProstoAlex пишет:

речь про strcpy(mydata.ss,sss.c_str()); ?

да, я имел в виду это - но у вас не сработает, я просто не заметил всех ваших косяков. Читайте ответ Евгения

А почему не сработает? Мне стало интересно.

ProstoAlex пишет:

я, конечно, ожидал готовый работающий код на блюдечке

А че так можно? :) А то мне код ядра для операционки нужен )))

b707
Offline
Зарегистрирован: 26.05.2017

anarch пишет:

b707 пишет:

да, я имел в виду это - но у вас не сработает, я просто не заметил всех ваших косяков. Читайте ответ Евгения

А почему не сработает? Мне стало интересно.

вы тоже читайте ответ Евгения :) в сообщении №8

anarch
Offline
Зарегистрирован: 10.09.2017

ну так в первом примере ТС компилятор должен был ругаться типа нельзя присвоит const char* к char.

а во втором случае н в наглую пихает char[7] в char.

string myString = "Hello";

struct DATA{
	char str[10];
};

DATA myData;

strcpy(myData.str, myString.c_str());

Что в такой записи вам не нравится. Или где то еще ТС напортачил и я не вижу?

b707
Offline
Зарегистрирован: 26.05.2017

anarch пишет:

string myString = "Hello";

struct DATA{
	char str[10];
};

DATA myData;

strcpy(myData.str, myString.c_str());

Что в такой записи вам не нравится. Или где то еще ТС напортачил и я не вижу?

у ТС то было не так

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ProstoAlex пишет:

Евгений, тогда более общий вопрос - как String (массив char) передать по easytransfer?

Я впервые слышу слово "easytransfer". Но если она умеет передавать 1 байт, то нужно просто сделать это столько раз, сколько символов в строке.

b707
Offline
Зарегистрирован: 26.05.2017

ЕвгенийП пишет:

Я впервые слышу слово "easytransfer". Но если она умеет передавать 1 байт, то нужно просто сделать это столько раз, сколько символов в строке.

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Вполне возможно. Я ж говорю, что впервые про неё слышу. Но, работать будет - стопудоф :-)))

anarch
Offline
Зарегистрирован: 10.09.2017

Что вы тревожите мои колокольчики. Причем здесь, что библиотека передает.

В примере в нее засовывают структуру. А поэтому вообще не чего преобразовывать не нужно.

В структуре вместо char указать String и все будет кошерно.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

anarch пишет:

В структуре вместо char указать String и все будет кошерно.

Точно? Вы у Раби консультировались?

b707
Offline
Зарегистрирован: 26.05.2017

anarch пишет:

В структуре вместо char указать String и все будет кошерно.

попробуйте себе ответить на очень простой вопрос - какой размер(в байтах) будет у этой структуры?

ProstoAlex
Offline
Зарегистрирован: 21.01.2015

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

b707
Offline
Зарегистрирован: 26.05.2017

ProstoAlex пишет:
В описании либы сказано, что она понимает "все типы данных". Но стринг не заработал, и в поисках правды в инете я нашел, что "все, кроме стринг".

Не "все" и не "все кроме стринг", а только типы данных. имеющие заранее известный размер. String к ним не относится, так как экземпляры String умеют подстраивать свой размер в зависимости от строки. который в него поместили. А библиотека Easytransfer устроена так, что в ней нужно заранее задавать размер структуры.

Есть и другие классы с настраиваемым размером, String не единственный.

кстати, String-ам при инициализации можно указать фиксированный размер. В таком разе может и заработает. Но даже если заработает, вряд ли это будет эффективно, гораздо проще и очевиднее использовать для строк массив char

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

b707 пишет:
В таком разе может и заработает.
Нет. Он по любому динамически память гребёт.

anarch
Offline
Зарегистрирован: 10.09.2017

b707 пишет:

anarch пишет:

В структуре вместо char указать String и все будет кошерно.

попробуйте себе ответить на очень простой вопрос - какой размер(в байтах) будет у этой структуры?

String 6 байт. И?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

anarch пишет:

String 6 байт. 

Нет

anarch
Offline
Зарегистрирован: 10.09.2017

ну по крайней мере sizeof(String) так думает

b707
Offline
Зарегистрирован: 26.05.2017

ЕвгенийП пишет:

b707 пишет:
В таком разе может и заработает.
Нет. Он по любому динамически память гребёт.

да, точно. Там наверно сама строка вообще не является элементом класса, а только ссылка на нее?

Тогда мои обьяснения выше, почему не работает -  неверные, хотя вывод остается тот же :) - работать не будет. Причина не в том, что размер String заранее неизвестен, а в том что библиотека EasyTransfer в принципе не знает, как String хранит данные и потому не может получить к ним доступа

b707
Offline
Зарегистрирован: 26.05.2017

anarch пишет:

ну по крайней мере sizeof(String) так думает

теперь положи в String строчку "Lo que tienes que saber este viernes" и проверь размер снова

anarch
Offline
Зарегистрирован: 10.09.2017

b707 пишет:

anarch пишет:

ну по крайней мере sizeof(String) так думает

теперь положи в String строчку "Lo que tienes que saber este viernes" и проверь размер снова

чудеса но те же 6 байт 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

2 байта указатель на сопсно строку и 4 байта служебной информации. Все правильно

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Какой бы длины у тебя строка ни была, указатель на нее будет по прежнему 2 унылых байта. 

anarch
Offline
Зарегистрирован: 10.09.2017

А дальше передать структуру побайтно, но не совсем безопасный способ мне кажется с использованием String.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Не передашь ты стринг по простому. 

anarch
Offline
Зарегистрирован: 10.09.2017
#include <iostream>
#include <cstring>

using namespace std;

std::string myString("Hello");

struct DATA{
	char str[6];
	string myStr;
};

DATA myData;

int main() {
	myData.myStr = "World";
	strcpy(myData.str, myString.c_str());
	for (int i=0;i<=(int)(sizeof(myData));i++)
	{
	cout << *(((char*)&myData)+i);
	}
	return 0;
}

Вывод: Hello Pp@ ? World

Этот мусор я предполагаю та самая служебная информация.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Простите, но Вы совсем неправы.

Во-первых здесь речь шла об ардуиновском классе String, а вовсе не об std::string

Ну, а дальше уже всё совсем на бред похоже.

b707
Offline
Зарегистрирован: 26.05.2017

anarch пишет:

А дальше передать структуру побайтно, но не совсем безопасный способ мне кажется с использованием String.

главный вопрос - нафига ? если есть char*

anarch
Offline
Зарегистрирован: 10.09.2017

Мдя... В ардуине такой фокус не проходит. Выводит char и кусочек мусора.

b707 пишет:

anarch пишет:

А дальше передать структуру побайтно, но не совсем безопасный способ мне кажется с использованием String.

главный вопрос - нафига ? если есть char*

Модно, молодежно использовать String )))

b707
Offline
Зарегистрирован: 26.05.2017

anarch пишет:

Мдя... В ардуине такой фокус не проходит. Выводит char и кусочек мусора.

anarch, вы в своем коде перепутали String и std::string. это абсолютно разные вещи. Так что ваш результат не "в ардуине такое не проходит", а просто  вообще ни о чем

anarch
Offline
Зарегистрирован: 10.09.2017

а в Ардуино есть std::string?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Из коробки - нет. Если сами установите, то пожалуйста.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Из std вардуино искаропки есть только std::nullptr и нихрена больше