Как упаковать 16-битное целое число, чтобы отправить его с помощью serial.write?
Пытаюсь отобразить значения, которые я получаю от чтения потенциометра (0-1023) в программе под названием "обработка".
когда я просто использую Serial.write(integer) и отображаю значение на линейном графике в режиме "обработка", линия максимизируется на уровне 256 и возвращается к 0 по мере изменения потенциометра.
Я понимаю, что это связано с тем, что serial.write может писать только в байтах(8 бит), поэтому мне нужно будет упаковать 16-битное целое число в 2 байта.
я подумывал о том, чтобы использовать union, но, как вы, наверное, догадываетесь, я новичок в arduino, поэтому мне не удалось заставить его работать.
вот код, который я пробовал:
union Data{ uint16_t now; } data;
void setup() { // put your setup code here, to run once:
Serial.begin(9600);
pinMode(A1, INPUT);
}
void loop() { // put your main code here, to run repeatedly:
uint16_t sensorVal = analogRead(A1);
union Data data;
data.now = sensorVal;
Serial.println(data.now);
//Serial.write(sensorVal);
delay(10); }
@Tom, 👍4
Обсуждение5 ответов
Вам нужно отправить uint16_t в виде двух отдельных байтов, из которых он состоит, по одному за раз, в любом порядке, в каком согласны ваш код Arduino и код на ПК: (сначала MSB, он же big-endian; или сначала LSB, он же little-endian).
Поскольку два устройства могут не синхронизироваться, вы также можете захотеть объединить два байта третьим, или "стартовым байтом". Выберите какое-нибудь фиксированное значение (например, 0xCC), в котором задана пара битов MSB, затем MSB, затем LSB. Ваш приемник может знать, что нужно искать это фиксированное значение, затем MSB (который, как он знает, не может иметь эти старшие биты, поскольку аналоговые данные имеют только 10 бит), затем LSB (который может иметь любое значение).
ПК должен принимать трехбайтовый пакет только в том случае, если он получил пакет, соответствующий этой схеме. В противном случае он ждет другого 0xCC (или любого другого значения, которое вы выберете), собирает еще два байта и повторяет попытку.
Отправьте 16-битное значение в виде двух 8-битных значений (с начальным байтом в соответствии сответом Джроберта):
Serial.write(0xCC); // Отправить начальный байт
Serial.write((sensorVal >>> 8) & 0xFF); // Сначала отправьте верхний байт
Serial.write((sensorVal & 0xFF); // Отправить нижний байт
Я проверял документацию для Serial.write()
Вы можете отправить массив из 2 8 Бит в виде Serial.write(buf, len)
Просто создайте буфер int, а затем используйте исходное целое число и выполните сдвиг битов. Обратите внимание, что & 255
используется для проверки отсутствия значений, превышающих 8 бит.
int data = 1000;
short int buf[2];
buf[0] = data & 255;
buf[1] = (data >> 8) & 255;
Serial.write(buf, 4);
Кроме того, в C имя массива используется в качестве указателя на первый элемент. Поэтому,если вы снова посмотрите документацию по Serial.write(buf, len)
, вы обнаружите, что, вероятно, вы можете получить указатель на значение int и записать 2 байта самостоятельно!
Serial.write(*data, 2);
или Последовательный.запись(&данные, 2)
Параметр длины для Serial.write-это байты, а не биты, @Chad G
зачем копировать байты в буфер? запись(&значение датчика, размер(int))
, @Juraj
@ChadG конечно, я давно не программировал, но некоторое время назад у меня была та же проблема. Это легко исправить во время программирования методом проб и ошибок, тем не менее я отредактирую свой пост., @BikerDude
@Juraj Я не копирую файл в своем втором решении, если вы посмотрите, нижний вариант совпадает с вашим ответом., @BikerDude
Если вы запрашиваете только числовое представление, попробуйте использовать функцию itoa ().
Предупреждение: Буфер должен быть достаточно большим, чтобы вместить наибольшее число со знаком плюс и завершающимся нулем: например, 32 - разрядная база-10: "-2147483648\0" = 12 символов.
Пример:
char buf[5]; // для сохранения строкового представления
Serial.write(itoa(sensorVal, buf, 10)); //itoa(значение для преобразования,где хранить,база)
Куда? Как? Ваш ответ должен включать какой-то пример кода, основанный на коде из вопроса. Вам не всегда нужно переписывать все целиком, но, по крайней мере, покажите соответствующие строки., @Chad G
@Chad G Есть ссылка, предоставленная для поощрения поиска и самооценки OP., @smajli
Это может помочь Передатчик
int valor;
byte val;
void setup() {
Serial.begin(9600);
}
void loop() {
valor=analogRead(A0);
val=map(valor,0,1023,0,179);
Serial.println(val);
Serial.write(val);
delay(100);
}
Рецептор
byte mensaje;
int valor;
void setup() {
Serial.begin(9600);
}
void loop() {
if (Serial.available()){
mensaje=Serial.read();
valor=mensaje;
Serial.print(valor);
Serial.println(" ");
}
}
Иногда полезно сопоставлять значения 0 .. 1023 с диапазоном 0 .. 179. Иногда проще сопоставить их с 0 .. 255 (путем деления/4 или сдвига вправо на 2 бита от 10-битного АЦП к 8-битному значению)., @DataFiddler
- Arduino Due vs Mega 2560
- Точность часов времени Arduino
- Регистры ввода-вывода SAM3X8E (Arduino Due)
- Построение графика на Python с использованием Tkinter Canvas
- Построение графика данных датчика Arduino в реальном времени на Processing, MatLab или Python
- Ручная установка Arduino Due
- analogRead всегда 1023 на Arduino Due
- Как выбрать пару SDA/SCL на Arduino Due?
почему вы печатаете() союз, но пишете() int? ожидает ли обработка числа в виде текста или в виде байтовых значений? возможно, вам нужен Serial.print(sensorVal), чтобы отправить значение в виде текста. кстати: объединение только с одним членом не является объединением. Вы можете написать int как write(&sensorValue, sizeof(int)), но я сомневаюсь, что Обработка поймет это, @Juraj