Передача данных по i2c
- Войдите на сайт для отправки комментариев
Чт, 28/04/2016 - 15:03
Здравствуйте,
Нужно от слейва получить массив, например int data[2]. Если отправить его можно, как Wire.wright(data,sizeof(data)) то как его правильно принять на мастере?
Неправильно написал.
Ну, например, побайтово, функцией Wire.read в цикле по размеру массива. Именно размеру в байтах, а не длине в элементах.
Я не могу понять, как c помощью Wire.read() можно принять переменную int. В примерах используется либо char либо byte.
Её нужно разбивать на пакеты по 1 байту?
Ну, принимаете и складываете побайтово. Ну, вот, если у Вас массив из двух целых. как Вы написали. Хорошо, теперь опишите ещё указатель на byte, который смотрит на начало этого массива. Примерно так:
После этого Вы можете спокойно принимать быйты и складывать их в pData[0], pData[1] ,pData[2], pData[3]
А когда все четыре байта сложите, то спокойно пользуйтесь Вашим массиво data - в нём будет всё правильно.
Вообще-то, грамотнее было сделать union, но я не буду пудрить Вам мозги. Да и наш указатель pData можно не располагать в памяти, а сделать макросом, но опять же - мозги пудрить не буду.
Спасибо. Буду пробовать
А можете про union и макрос рассказать или ссылкой поделиться. Интересно узнать, как было бы грамотнее
Про union. Ссылка, пример:
void setup(void) { Serial.begin(115200); // При таком объявлении // data и bData будут занимать ОДНО И ТОЖЕ место в памяти. union { int data[2]; byte bData[sizeof(data)]; } td; // Обращаться к ним можно так // Срачала побайтово сформируем td.data[0] td.bData[0] = 2; // в младший байт элемента td.data[0] положили 2 td.bData[1] = 7; // в старший байт элемента td.data[0] положили 7 // Теперь побайтово сформируем td.data[1] td.bData[2] = 255;// в младший байт элемента td.data[1] положили 255 td.bData[3] = 2; // в старший байт элемента td.data[1] положили 2 // Теперь td.data[0] должен быть равен 0x0702 = 1794 // а td.data[1] должен быть равен 0x02FF = 767 // Убедимся в этом Serial.print("td.data[0] = "); Serial.print(td.data[0], HEX); Serial.print("(hex) = "); Serial.println(td.data[0]); // Serial.print("td.data[1] = "); Serial.print(td.data[1], HEX); Serial.print("(hex) = "); Serial.println(td.data[1]); } void loop(void) {} /////////////////////////// // РЕЗУЛЬТАТ // // td.data[0] = 702(hex) = 1794 // td.data[1] = 2FF(hex) = 767Про макрос. Ссылка. Пример:
// Определяем макрос #define pData ((byte *)(&data[0])) void setup(void) { Serial.begin(115200); int data[2]; // Обращаться к ним можно так // Срачала побайтово сформируем data[0] pData[0] = 2; // в младший байт элемента data[0] положили 2 pData[1] = 7; // в старший байт элемента data[0] положили 7 // Теперь побайтово сформируем data[1] pData[2] = 255;// в младший байт элемента data[1] положили 255 pData[3] = 2; // в старший байт элемента data[1] положили 2 // Теперь data[0] должен быть равен 0x0702 = 1794 // а data[1] должен быть равен 0x02FF = 767 // Убедимся в этом Serial.print("data[0] = "); Serial.print(data[0], HEX); Serial.print("(hex) = "); Serial.println(data[0]); // Serial.print("data[1] = "); Serial.print(data[1], HEX); Serial.print("(hex) = "); Serial.println(data[1]); } void loop(void) {}Можете запустить, попробовать.
Кстати, в обоих случайх, никакой лишней памяти в области данных мы не расходуем.
Union похож на струтуру. Спасибо огромное.
Могу ошибаться, но разве это указатель? Это же адрес, вроде, константа т.с. Указатель - это переменная, содержащая адрес. Не? :)
Union похож на струтуру. Спасибо огромное.
Юнион и есть структура, в которой переменные раполагаются начиная с одного адреса поверх друг друга.
Могу ошибаться, но разве это указатель? Это же адрес, вроде, константа т.с. Указатель - это переменная, содержащая адрес. Не? :)
Вы о чём? О макросе? Если о нём, то да, указатель. Посмотрите, какой у какой у него тип. Переменной нет, потому что это не переменная, а выражение, имеющее тип byte *. Разве результат выражения не может быть указателем? Да и константой указатель имеет право быть. В данном случае выражение будет вычислено на этапе компиляции, потому никакой нагрузки в код нон не вносит. Всё с ним в порядке.
Евгений, а с Вами есть какая нибудь прямая связь? У меня видимо будет много вопросов, на которые, возможно, вы можете дать ответы
Нет, но я здесь часто бываю
Могу ошибаться, но разве это указатель? Это же адрес, вроде, константа т.с. Указатель - это переменная, содержащая адрес. Не? :)
Вы о чём? О макросе? Если о нём, то да, указатель. Посмотрите, какой у какой у него тип. Переменной нет, потому что это не переменная, а выражение, имеющее тип byte *. Разве результат выражения не может быть указателем? Да и константой указатель имеет право быть. В данном случае выражение будет вычислено на этапе компиляции, потому никакой нагрузки в код нон не вносит. Всё с ним в порядке.
Гм... Тут уже моего С, очевидно, мало, чтобы разобраться в тонкостях терминологиив нём применяемой...
С точки зрения теории указатель и адрес - это разные вещи... Указатель сам обязан иметь адрес, ибо является субъектом данных, а полученный на этапе компиляции "указатель"/адрес есть константа.
С точки зрения теории указатель и адрес - это разные вещи... Указатель сам обязан иметь адрес, ибо является субъектом данных, а полученный на этапе компиляции "указатель"/адрес есть константа.
Эк, куда Вас занесло! Ну, разговор, как я понимаю чисто абстрактно-теоретический? Хорошо.
Я вообще-то, занимался языками (теорией) но специализировался на другом классе языков, поэтому как-то "зуб давать" за то, что я сейчас скажу я бы не стал. Если интересно. я могу поговорить с "язычниками". которые специализируются именно на этом классе языков, но я уверен. что смысла обсуждать такие тонкости на русском языке нет никакого потому, что официального перевода стандарта С++ на русский язык не существует в природе (а значит и чётко определённой официальной терминологии на русском языке нет). В оргигинале же стандарта есть очень много нюансов (типа "pointer value", "pointer type", "pointer constant" и т.п. ), которые на русский переводятся как положит Бог на душу переводчикам.
В стандарте нигде не сказано, что указатель обязан иметь адрес, но я готов это принять, если говорить об указателе, как о переменной типа "указатель на". Однако, стандарт предполагает наличие не только переменных, но и других объектов типа "указатель на", например, стандартом чётко определяется литерал nullptr, который, разумеется, никакого адреса не имеет. Вы имеете полное право сказать, что это не указатель, а лишь "значение, которое может быть преобразовано у типу "указатель на"", ради бога, я спорить не буду, соглашусь. Также я готов согласиться. что мои константы из примеров не указатели, а "значения, которые могут быть преобразованы ...", пожалуйста, я согласен. Спорить тут неочем, поскольку спор идёт о терминологии, которая нигде официально не утверждена (на русском языке). Бессмыслица полная.
И вообще, это разговор не для форума об Ардуино, а для бесеlы за пивом после долгого рабочего дня конференции по теории языков. Если хотите, я могу прислать Вам приглашение на ближайшёю такую конференцию (летом), а здесь давайте прекратим нашу "злостную флудерастию" :))))
И вообще, это разговор не для форума об Ардуино, а для бесеlы за пивом после долгого рабочего дня конференции по теории языков. Если хотите, я могу прислать Вам приглашение на ближайшёю такую конференцию (летом), а здесь давайте прекратим нашу "злостную флудерастию" :))))
Хорошо. Согласен.
Где будет конференция? :)
Переславль-Залесский, она ежегодно проходит.
Кстати, если интересно, то там же в ноябре ежегодно проходит "Суперкомпьютерный форум".
Переславль-Залесский, она ежегодно проходит.
Кстати, если интересно, то там же в ноябре ежегодно проходит "Суперкомпьютерный форум".
Вы же тут сделаете объявление предварительно, ближе к началу события?
Ну, сделаю, но регистрироваться можно хоть сейчас, например, чтобы поучаствовать в выдвижении номинантов на ежегодную премию. Она там очень демократична - никаких высоколобых дядек-жюри, выдвигать может любой, а потом голосуют все. Причём система голосование преференциальная.
Только не надо мне задавать вопросов "как Вы боретесь с теоремой Эрроу" - никак не боремся, это математическая теорема, чего с ней бороться? Да, идеальная, доведённая до совершенства и абсолюта демократия есть ни что иное, как диктатура - это математически доказанный факт и бороться тут не с чем.
Здравствуйте, у меня возникла проблема над которой я уже бьюсь несколько дней, и она заключается в том что мне надо с NodeNCU управлять ардуино, передавать много переменных которые я буду получать по Wifi но у меня никак не получается организовать передачу массивов между платами, простые сообщение типа "Hello Arduino" передаются запросто, а вот масив с переменными не хочет, вот примеры кодов:
Код для NodeMCU
#include <Wire.h> byte data2[4]; byte data[4]={400, 8, 1, 6}; void setup() { Serial.begin(115200); /* открываем серийный порт для дебаггинга */ Wire.begin(D1, D2); /* задаем i2c мост через контакты SDA=D1 и SCL=D2 на NodeMCU */ } void loop() { Wire.beginTransmission(8); /* Начинаем передачу на адресе 8 */ Wire.write("Hello Arduino"); /* Отправляем "hello Arduino" */ Wire.write(data, 4); /* отправить массив значения*/ Wire.endTransmission(); /* прекращаем передачу */ Wire.requestFrom(8, 13); /* запрашиваем и считываем данные с 8 и 13 адреса slave устройства */ while(Wire.available()){ char c = Wire.read(); Serial.print(c); } Serial.println(); delay(1000); }Код для ардуино нано:
#include <Wire.h> byte data[4]; int ints; byte data2[4]={50, 800, 10, ints}; void setup() { Wire.begin(8); /* задаем на шине i2c 8 адрес */ Wire.onReceive(receiveEvent); /* регистрируем полученное событие */ Wire.onRequest(requestEvent); /* регистрируем запрошенное событие */ Serial.begin(115200); /* открываем серийный порт для дебаггинга */ } void loop() { Wire.write(data2, 4); /* отправить массив значения*/ } // Функция для извлечения любых принимаемых данных от мастера на шину void receiveEvent(int howMany) { while (0 <Wire.available()) { char c = Wire.read(); /* получаем байт как символ*/ Serial.print(c); /* выводим символ в серийный порт */ } Serial.println(); /* переходим на новую строку */ } // Функция для извлечения любых отправляемых данных от мастера на шину void requestEvent() { Wire.write("Hello NodeMCU"); /* отправляем по запросу строку "Hello NodeMCU" */ }Ориентировался на статью по этой ссылке: https://voltiq.ru/nodemcu-v3-connecting-to-arduino-via-i2c/ схему подключение тоже от туда взял, на выходе получаю такие сообщения:
Т.е. Вы привели нам работающий код, по которому Вам помощь не нужна, а неработающий - по которому нужна помощь, решили оставить в секрете. Логичное решение.
В этом коде не работает передача массивов между платами и я не знаю как ее сделать.
у меня никак не получается организовать передачу массивов между платами, простые сообщение типа "Hello Arduino" передаются запросто
Вот код для NodeMCU который я хочу сделать:
#include <ESP8266WiFi.h> #include <Ticker.h> #include <ArduinoJson.h> #include <Wire.h> #include <ESP8266WebServer.h> #define dev_id 12345678 const char* ssid = "NodeMCU"; // Enter SSID here const char* password = "12345678"; //Enter Password here /* Put IP Address details */ IPAddress local_ip(192,168,0,5); IPAddress gateway(192,168,0,5); IPAddress subnet(255,255,255,0); //ESP8266WebServer server(80); char c2; int p=100; WiFiServer server(80); Ticker blinker; String header; int n=100; int n2=0; int del=4; int tmp; int id; int idt; int dir1; int m1d; int m1s; int m1e; int m1dt; int m1st; int m1et; String tmps=" "; void setup() { //ESP8266 Serial.begin(115200); /* открываем серийный порт для дебаггинга */ Wire.begin(D1, D2); /* задаем i2c мост через контакты SDA=D1 и SCL=D2 на NodeMCU */ Serial.println("Starting..."); Serial.print("Connecting to "); Serial.println(ssid); WiFi.softAP(ssid, password); WiFi.softAPConfig(local_ip, gateway, subnet); delay(100); // Print local IP address and start web server Serial.println(""); Serial.println("WiFi connected."); Serial.println("IP address: "); Serial.println(WiFi.localIP()); server.begin(); } void loop() { WiFiClient client = server.available(); // Listen for incoming clients // listen for incoming clients if (client) { // Serial.println("Client"); // an http request ends with a blank line boolean currentLineIsBlank = true; while (client.connected()) { while(client.available()) { char c = client.read(); // if you've gotten to the end of the line (received a newline // character) and the line is blank, the http request has ended, // so you can send a reply if (c == '\n' && currentLineIsBlank) { // Here is where the POST data is. header = ""; while(client.available()) { // Serial.write(client.read()); char c = client.read(); // read a byte, then header += c; } Serial.println(header); StaticJsonBuffer<200> jsonBuffer; JsonObject& root = jsonBuffer.parseObject(header); if (!root.success()) { Serial.println("parseObject() failed"); return; } //const char* m1ds = root["m1d"]; m1dt=root["m1d"]; m1st=root["m1s"]; m1et=root["m1e"]; idt=root["id"]; if(idt==dev_id) { if((m1dt==255)&&(m1st==255)&&(m1et==255)) { Serial.println("MOTOR STOPS"); } else { stepper_on(); } } Serial.println(); header = ""; // Serial.println("Sending response"); // send a standard http response header client.println("HTTP/1.0 200 OK"); client.println("Content-Type: text/html"); client.println(); client.stop(); } else if (c == '\n') { // you're starting a new line currentLineIsBlank = true; } else if (c != '\r') { // you've gotten a character on the current line currentLineIsBlank = false; } } } //Serial.println("Disconnected"); } } void stepper_on(void) { if (m1s == 1){ n = 1300; } else if (m1s == 2){ n = 1200; }else if (m1s == 3){ n = 1100; }else if (m1s == 4){ n = 1000; }else if (m1s == 5){ n = 900; }else if (m1s == 6){ n = 800; }else if (m1s == 7){ n = 700; }else if (m1s == 8){ n = 600; }else if (m1s == 9){ n = 500; }else if (m1s = 10){ n = 400; } byte data[5]={m1et, m1dt, n, m1e, m1s}; Wire.beginTransmission(8); /* Начинаем передачу на адресе 8 */ Wire.beginTransmission(8); /* Начинаем передачу на адресе 8 */ Wire.write(data, 5); /* отправить массив значения*/ Wire.endTransmission(); /* прекращаем передачу */ }А вот для ардуино:
#include <Wire.h> byte data[4]; // defines pins numbers const int stepPin = 4; const int dirPin = 3; const int enPin = 5; void setup() { Wire.begin(8); /* задаем на шине i2c 8 адрес */ Wire.onReceive(receiveEvent); /* регистрируем полученное событие */ Wire.onRequest(requestEvent); /* регистрируем запрошенное событие */ Serial.begin(115200); // Sets the two pins as Outputs pinMode(stepPin,OUTPUT); pinMode(dirPin,OUTPUT); pinMode(enPin,OUTPUT); digitalWrite(enPin,LOW); } void loop() { digitalWrite(enPin,LOW); // Функция для извлечения любых принимаемых данных от мастера на шину void receiveEvent(int howMany) { while (0 <Wire.available()) { char c = Wire.read(); /* получаем байт как символ*/ Serial.print(c); /* выводим символ в серийный порт */ } Serial.println(); /* переходим на новую строку */ } if (data[1] == 1){ digitalWrite(dirPin,HIGH); // Enables the motor to move in a particular direction // Makes 200 pulses for making one full cycle rotation for(int x = 0; x < 200; x++) { digitalWrite(stepPin,HIGH); delayMicroseconds(data[3]); digitalWrite(stepPin,LOW); delayMicroseconds(data[3]); } } if (data[2] == 1){ digitalWrite(dirPin,LOW); //Changes the rotations direction // Makes 400 pulses for making two full cycle rotation for(int x = 0; x < 200; x++) { digitalWrite(stepPin,HIGH); delayMicroseconds(data[3]); digitalWrite(stepPin,LOW); delayMicroseconds(data[3]); } } digitalWrite(enPin,HIGH); }Это полные коды в которых ничего не убрано
Вы не так заходите.
Напишите специальный короткий код, который только демонстрирует Вашу проблему. Он не будет более 10 строк. Там должна быть показана Ваша проблема и не должно быть ничего лишнего. Вот этот код опубликуйте и задайте по нему конкретные вопросы.
А то Вы первый раз выложили "хелло", которые по Вашим словам отлично работают. Теперь какие-то сотни строк, в которых чего только нет. Кто в этом разбираться будет? Вопрос нужно подготовить. Вот и подготовьте.
А нельзя Wire.endTransmission(); из стр.192 как бы несколько позже вызывать? строки 189 и 190 намекают на вашу неуверенность. JSON.... Вы вэб-дизайнер? Им обычно не везет в ардуине.
Хорошо, проблема состоит в том что я не могу организовать передачу массива переменных, переменные являются числами от единиц до тисяч. Передача осуществляется от мастера NodeMCU к слейву ардуино нано:
Пример кода NodeMCU
#include <Wire.h> byte data[4]={4000, 8, 1, 60}; void setup() { Serial.begin(115200); /* открываем серийный порт для дебаггинга */ Wire.begin(D1, D2); /* задаем i2c мост через контакты SDA=D1 и SCL=D2 на NodeMCU */ } void loop() { Wire.beginTransmission(8); /* Начинаем передачу на адресе 8 */ Wire.write(data, 4); /* отправить массив значения*/ Wire.endTransmission(); /* прекращаем передачу */ Wire.requestFrom(8, 13); /* запрашиваем и считываем данные с 8 и 13 адреса slave устройства */ }#include <Wire.h> byte data[4]; void setup() { Wire.begin(8); /* задаем на шине i2c 8 адрес */ Wire.onReceive(receiveEvent); /* регистрируем полученное событие */ Serial.begin(115200); /* открываем серийный порт для дебаггинга */ } void loop() { delay(100); } // Функция для извлечения любых принимаемых данных от мастера на шину void receiveEvent(int howMany) { while (0 <Wire.available()) { char c = Wire.read(); /* получаем байт как символ*/ Serial.print(c); /* выводим символ в серийный порт */ } Serial.println(); /* переходим на новую строку */ }Уже лучше. Теперь сделайте следующее
1. перевставьте первый кусок как положено
2. выложите заодно, что они (эти куски кода) печатают в сериал.
Я пока доеду до дома, а там гляну.
byte data[4]={4000,
...однако
Не знаю можно ли позже вызвать ети строки, тут я действительно неуверен. А по поводу JSON нет я не веб дизайнер.
Вот что выдает ардуино:
а чего тогда 4000 в байт запихиваете? Такое тока вэбдизайнерам позволено ;) Впишите delay(100); после 12 строки. Ну и после 13 тоже для начала. Строку 15 вобще к чему вписали?
отсюда https://forum.arduino.cc/index.php?topic=556381.0 шоле вдохновение берете?
Нет, но похоже с одного сайта
С чтением принимаемой информации разобрался, проблема оказалась в чтении этой информации, а более конкретно в char, ардуина принимала информацию и выводила с помощью char (слова).
while (0 <Wire.available()) { char c = Wire.read(); /* получаем байт как !!!символ!!!*/ Serial.print(c); /* выводим символ в серийный порт */замена на byte помогла
while (0 <Wire.available()) { byte c = Wire.read(); /* получаем байт */ Serial.println(c); /* выводим символ в серийный порт */Так проблема решена? Или ещё вопросы остались?
Еще вопросик, как правильно реализовать чтение значений которые пришли, то-есть, отправляется такой массив {40, 8, 1, 60}, на приемной стороне мы его принимаем как 408160 или как
40
8
1
60
как задать переменным эти значения или же как считывать только одно из них?
Ну, а как Вы сейчас считываете?
bytec = Wire.read();Вы присвоили пришедшее значение переменной с. Так и делайте с остальными значениями