Доброго дня. Есть три ведомые платы, одна ведущая. Все связаны по i2c По запросу от ведущей ведомые возвращают данные: от одного до десяти целых чисел в диапазоне от -100 до 100. (Длина пакета разная для трех плат, но в ходе работы не меняется. Т.е. например набор 3 числа от платы 1,3 от платы 2,10 от платы 3. Задается при первоначальном программировании) Как корректно передавать данные? Иными словами - как сформировать пакет байт на стороне ведомого и как корректно востановить из пакета байт целые числа на стороне ведущего? Киньтесь ссылкой если уже обсуждалось. Спасибо.
Эту библиотеку я смотрел. Насколько я понял - что бы она работала - необходима одинаковая длина пакета на всех платах. У меня - длина пакета разная на разных платах.
Со стороны передатчика (слэйв I2C)написан код: Код (Text): void setup() { Wire.begin(2); Serial.begin(9600);Wire.onRequest(requestEvent); } void loop() { sensorValue = analogRead(analogInPin); outputValue = map(sensorValue, 0, 1023, -100, 100); //приводим к диапазону -100 100 void requestEvent() Serial.println(outputValue); { // Wire.write(outputValue); Wire.write(lowByte(outputValue)); Wire.write(highByte(outputValue)); } } Со стороны приемника (мастер I2C) написан код: Код (Text): #include <Wire.h> #include <LiquidCrystal.h> int data = 0; LiquidCrystal lcd(10, 4, 5, 6, 7, 8); void setup() { lcd.begin(16, 4); lcd.print("OK"); Wire.begin(); Serial.begin(9600); } void loop() { lcd.setCursor(0, 1); lcd.print(millis()/1000); Wire.requestFrom(2, 2); byte i = 0; byte buffer[2] = {0, 0}; while(Wire.available()) { buffer[i] =Wire.read(); i++; data = 0; data |=buffer[1] & 0xFF; data =data << 8; data |=buffer[2] & 0xFF; } Serial.print("Data="); Serial.println(data); lcd.setCursor(-4,3); lcd.print(data); delay(500); } Выдает на стороне мастера неправильное значение... То -88 то -4, но ни разу не то что подается слэйвом. Что я делаю не так?
Код (Text): outputValue = map(sensorValue, 0, 1023, -100, 100); А почему бы это не делать со стороны мастера?
Это - частный случай. Просто сделал так для отладки. Кручу потенциометр - смотрю что шлется. В общем случае - у меня будут пересылаться не только данные с сенсора но и отрицательные числа, получаемые расчетным путем. Как двухбайтного хранения - целые, так и четырехбайтные - float. В любом случае - как их правильно пересылать - важно разобраться. Пока у меня не получается.
Вы все-таки определитесь с размерностью, от этого и реализация будет зависеть, потому как диапазоны -100...+100 и -398,20...+400,37 нужно кодировать совершенно по-разному.
Знаков после точки шесть. Предельные значения -360 + 360. Передаваться будут географические координаты, курс, скорость.... Для координат - шесть знаков после запятой, курс - хватит одного знака. Сдужебная информация - и вовсе целыми числами будет кодироваться. Разрабатываю навигационно -управляющую систему для катера и хочу проверить несколько идей с разнесенными приемниками. Каждая платка обрабатывает свой приемник и потом мастеру по запросу данные передает.
Я в общем то электромеханикой больше занимался всю жизнь. А не программированием. По этому и спрашиваю как сделать.... Ежели ткнете носом в пример кода аль толковый учебник - буду благодарен. ежели ткнете в рабочий код пересылающий три числа, скажем 160.123456 -80.654321 255 по I2C - так и вовсе счастлив буду...
На самом деле если вы желаете передать допустим число с плавающей точкой как целочисленные значения а потом его собрать. Можно использовать объединения. Вот демонстрационный код: Код (Text): #include <iostream> int main( void ) { union mixValue { float floatValue; char charValue[ 4 ]; }; mixValue mV; mV.floatValue = 12.74; std::cout << mV.floatValue << std::endl; mV.floatValue = 0; std::cout << mV.floatValue << std::endl; mV.charValue[0] = 10; mV.charValue[1] = -41; mV.charValue[2] = 75; mV.charValue[3] = 65; std::cout << mV.floatValue << std::endl; return 0; } Вывод: Код (Text): 12.74 0 12.74 Таким образом достаточно передать 4 байта данных а на другом конце вставить их на свои места в такое же объединение. У меня в системе для float отводилось 4 байта. отсюда и размер массива char. Главное как я понимаю что бы порядок хранения байтов в памяти совпадал у задействованных МК, в противном случае придется это решать Если вы не совсем поняли как работает объединение, то прочитайте о нем и все сразу станет понятно Фактически это кусочек памяти который можно интерпретировать по разному получая доступ к тому что там записано либо как к float либо как в массиву char и тд и тп.
Стало еще непонятнее. Добавил коментарии в ваш пример. Код (Text): #include <iostream> int main( void ) { union mixValue { float floatValue; char charValue[ 4 ]; }; mixValue mV; mV.floatValue = 12.74; *ИСХОДНОЕ ЧИСЛО* std::cout << mV.floatValue << std::endl; *СИЛЬНОЕ КОЛДУНСТВО* mV.floatValue = 0; std::cout << mV.floatValue << std::endl; mV.charValue[0] = 10; *А ВОТ ЭТИ ПРИСВОЕНИЯ ЗАЧЕМ???* mV.charValue[1] = -41; mV.charValue[2] = 75; mV.charValue[3] = 65; std::cout << mV.floatValue << std::endl; return 0; }
В принципе - математика с фиксированной точкой мне подходит. Базовые чипы в системе - Mega8 Главное, что бы работало с числами вида S XXXX.YYYYYY где S знак плюс или минус XXXX целая часть числа до 9999 (мне хватит за глаза) YYYY дробная часть числа По большому счету - даже не нужно пересылать несколько подобных чисел за один пакет. В любом случае буду реализовывать диалоговую систему - т.е писать протокол запрос - ответ. На человеческом языке примерно такая логика Что то вроде: М=Мастер С=слэйв М: С1, сообщить статус С1: 111.222222 /Все работает/ М: С1, скорость? С1: 30.250000 М: С1, курс С1: 135.200000 М:С1, широта С1:-60.234567 М:С1, дистанция до точки C1: 2300.100000 Как протокол реализовать - это в примерах Ардуины более менее понятно написано. Как с GPS работать - тоже. А вот пересылка данных - уже третий день вою от напряга мозга Главное - отработать код для пересылки 1 числа указанного формата.... А это - не получается пока....