Sending array data from Processing to Arduino
I successfully managed to send a single integer from processing to Arduino but now I want to send an array of three integers and I can’t get it working. I want to create a buzzer feedback with Arduino which processing will control which buzzer to activate. For example, the data send from processing should be [1,0,1] meaning sensor 1 and 3 should start working. The buzzers should be able to be activated simultaneously in case that [1,1,1] goes through.
This is the code I have so far: I am trying to understand what data is being sent back to Arduino to know how to use it and I keep getting either a null value or a random integer.
I’m trying to learn how to do this so apologies if the code is bad.
Arduino
Processing
1 Answer 1
If you’re data is an array that always has 3 items and each of those items are always either 1 or 0 (bits), you could store that whole data in a single byte (and still have 5 more bits to spare). Sending and receiving a byte is pretty simple with Arduino.
Here’s a basic sketch that shows you how to flip 3 bits in a single byte:
Use keys ‘1’,’2′ and ‘3’ to flip the bits.
Note that in keypress we’re always updating the same byte. The text will display the decimal value first and the binary value bellow.
This is the most efficient way to send your data and the simplest in terms of serial communication. On the Arduino side you can simply use bitRead() on the byte you get from Serial.read() . For more on binary/bits/bytes be sure to read the BitMath Arduino tutorial. Binary may seem intimidating at first, but it’s really not that bad once you practice a bit and it’s totally worth knowing.
Here’s an updated version of the code above that sends the byte to Arduino on the first available serial port (be sure to change Serial.list()[0] with what makes sense for your setup and press ‘s’ to send an update to Arduino:
And here’s a super basic Arduino sketch:
If you connect 3 LEDs to pins 10,11,12 you should them toggle as you press keys ‘1’,’2′,’3′ then ‘s’ in Processing
One way around binary in Processing could be using a String representation of your data (e.g. «00000101» for [1,0,1] ) and unbinary() to convert that String to an integer value you can write to serial, but it will be a bit annoying to getting and setting a character at an index (and potentially parsing that char to it’s integer value and back)
When you need to send more than a byte things get a bit more complicated as you need to handle data corruption/interruptions, etc. In these situations it’s best to setup/design a communication protocol based on your needs and this isn’t easy if you’re just getting started with Arduino, but not impossible either. Here’s an example, there are many more online.
One quick and dirty thing you could try is sending that data as string terminated by a new line character ( \n ) which you could buffer until in Arduino then read 4 bytes at a time, discarding the \n when parsing:
e.g. sending «101\n» from Processing, representing [1,0,1] then on the Arduino side use Serial.readStringUntil(‘\n’) and a combination of charAt() and toInt() to access each integer within that that string.
Here’s an example Processing sketch:
And an Arduino one based on Arduino > File > Examples > 04.Communication > SerialEvent:
Note this is more prone to error and used 4 times as much data as the the single byte option.
Sending and receiving different types of data via I2C in Arduino
I have found a few good tutorials on how to send and receive data via I2C in connected arduinos. My limitation is now how to transmit different types of data like for instance, long, float, etc. Right now the communication via I2C using the wire library only allows transmission of numbers between 0 and 255. How can one transmit different types of numbers?.
In my code a master receives three types of data from the slave, and it send data of a fourth variable to the slave.
here is the code for the master
here is the code for the slave
3 Answers 3
I2C is truly a powerful option of Arduino, for too many reasons; yet the amount of tutorials available are not that many and unfortunately are too complicated for the average person.
After working on this for 2 days, I think I have a way to transfer pretty much anything between master and slaves and viceversa. Note that I2C does not transfer floats or even integers larger than 255, there are several ways to go about this and here is a good tutorial http://www.gammon.com.au/i2c and even a library: http://forum.arduino.cc/index.php?topic=171682.0
The solution I found was simpler. Basically we convert any value, string, number, text, float, you name it, and turn into a variable char, which can be transferred via I2C. Once transferred, you can convert back to a number although in my case below, I just wanted to display the data from the slave.
Here is the code. I provide comments on different parts for clarity. I hope this helps. it worked for me.
Arduino.ru
Прием и передача массива по uart
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Уважаумые форумчане, помогите решить вопрос по приему и передачи массива значений. Написал скетчи, а работать не хочет. Делаю дистанционное управление танком, это проба передачи данных управления. Передача:
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
вот на передачу.
я честно сказать точно не помню как пишется. но там что то вроде должно быть.
максим тебе точно скажет как там правильно пишется
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Передатчик вроде работает, в мониторе ком порта данные идут нормально. Мне кажется, что я где-то с приемником накосячил. Если поменять analogWrite на servo[i].write(x), то все работает.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
так у вас ваш или тот что я предложил нормлаьно работает?
если вы управляете мотором при чем здесь servo библиотека?
и по моему в приемнике неправильно сделано. но я не уверен и не буду утверждать
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Передатчик нормально работает(Вроде). Servo, для примера. Я тоже считаю, что проблема где-то в приемнике, но не могу понять где((
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
создайте массив. запишите туда сначала все значения. а потом уже управляйте моторами и чем хотите
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
и еще добавьте ответ на передатчик что все получено. и можно снова слать. а то передатчик все время шлет, а приемник может еще не успел обработать. буфер переполнится. данные потеряются
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Не совсем понял про массив((.
Вот так работае идеально, передача:
И для обмена нужно двухстороннюю передачу делать, а у меня с трансиверами проблемы. Если по почте заказывать, месяц ждать, весь интерес пройдет, а до города ехать 650 км. На севере живу. А кто такой Максим? Как его пригласить в наш диалог, или связаться с ним?
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
в самом первом посте — у вас буферы на передачу и на прием разной длины
и вот это как-то. ммм. одним словом, так нельзя :)
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Буферы делал одинаковые, просто при вставке один код старый взял. Даже при одинаковых размерах не работает.
Что здесь не так? Если не считать, что вместо int out [2] нужно поставить int out [3]
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
чтение можно в цикл засунуть. только непонятно как вы считываете аналоговое значение с цифрового входа? что за ардуина такая
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Это все работает. То, что вы сейчас написали, тот же код только немного по другому оформлен. А в каком месте я считываю аналог с цифры.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
analogRead (0) = analogRead (A0) — всЁ равно.
digitalRead(A0) = digitalRead (14) (uno, duemilanove, decimila) аналогично
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Этого ни кто и не отрицал. Я считываю цифру с аналога, это нормально. Мне просто удобнее писать А0 и т.д. Просто у меня Mega и аналог там подписан как А0 и т.д.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Только непонятно как в этом цикле написать A0, A1, A2.
Вряд-ли for ( int i = A0 ; i Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Буферы делал одинаковые, просто при вставке один код старый взял. Даже при одинаковых размерах не работает.
Что здесь не так? Если не считать, что вместо int out [2] нужно поставить int out [3]
а это, по вашему, ерунда? ошибки с памятью (невыделение, запись низвестно куда, чтение неизвестно откуда) — значительная доля всех глюков.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Да это не важно. Что автоматом вместо i расставятся цифры, что я явно задам, передатчик работает. На данный момент я это знаю точно.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
А я не сказал, что это ерунда. Наоборот, я спросил, что там не так.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Только непонятно как в этом цикле написать A0, A1, A2.
Вряд-ли for ( int i = A0 ; i Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Да это не важно
вы не понимаете основ использования памяти. вылезание за границы массива является грубейшей ошибкой. если на пальцах, то нельзя впихивать невпихуемое
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Да это не важно
вы не понимаете основ использования памяти. вылезание за границы массива является грубейшей ошибкой. если на пальцах, то нельзя впихивать невпихуемое
Это написано было для trembo. А у вас я спросил, как можно по другому сделать, чтобы впихнулось)) И вообще, что-то со всем кодом не так. За ночь сделал много открытий на этом форуме, сейчас попробовал по другому сделать, но. Снова не нравится. Какие-то непонятные скачки по портам где выхода.
Вот код приемника:
А это передатчик:
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Это можно записать как:
for (int i=0; i Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Это можно записать как:
for (int i=0; i <
buf[i] = map(analogRead(Ai), 0, 1023, 0, 180);
>
Если очень надо то можно так:
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Это можно записать как:
for (int i=0; i <
buf[i] = map(analogRead(Ai), 0, 1023, 0, 180);
>
Если очень надо то можно так:
Да это не в этом проблема. Передатчик работает, номально передает данные. мне их принять надо корректно. И второй вариант кода как-то более рабочий.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Да это не в этом проблема. Передатчик работает, номально передает данные. мне их принять надо корректно. И второй вариант кода как-то более рабочий.
А с передачей данных всегда проще, чем с приемом. Тут главное понимать, что вы работаете с асинхронным приемо-передатчиком (UART) — т.е. приемнику пофиг когда, как, и примет ли вообще другая сторона посланные данные, он плюнул их в «черную дыру» и забыл. А вот приемник должен уметь каким-то образом определить начало передачи пакета данных и их окончание (или длину), проверить контрольную сумму принятых данных. И второй постулат: приемо-передатчик пересылает данные байтами, хоть вы в прогрмме и можете вызвать какую-либо функцию передачи word, long, float, физически будет передана последовательность байт. Теперь мы стали ближе к понимаю, что при работе с данными нам нужен протокол передачи данных.
От лирики к практике:
1) Не факт, что последний ваш вариант правильней, чем первый. В первом варианте я усмотрел правильную вещь — байт синхронизации пакета данных 0xFF:
buf[0] = map(analogRead(0), 0, 1023, 0, 254); — тут вначале не понял почему ограничение по 254
Serial .write(0xff); // synchronize — а теперь понял
2) В последнем примере вы передаете сначала символ, а потом данные в диапазоне 0-254, а где гарантия что данные из map() и ваши символы не совпадут, тогда весь прием поедет? А где гарантия, что результат map() и digitalRead() имеет размерность 1 байт и в будущем не изменится?
3) Как надо делать: создаем свой протокол передачи данных. У вас был массив — уже хорошо, но на практике лучше использовать структуру, она гибче в использовании в коде и позволяет создать пакет данных с разными типами/размерностью полей.
Пока кратко, а то позно уже, а мне на рыбалку рано вставать :)
а) Создаем структуру, в которой учитываем следующие поля: 1-2 байта синхронизации — можете свои инициалы впихнуть (будет брэндовый протокол:), длина пакета (определиться с длиной чего?, от и до?), ID сообщения в пакете (вдруг ваш протокол получит развитие в других ваших проекта и будете предавать разные пакеты данных — с разными ID и соответственно с разной структурой пакета), 1-2 байта контрольной суммы ( определиться с длиной подсчета от и до? ). Со структурой пакета все!
б) Сразу продумываете алгоритм подсчета контрольной суммы. Реализуете ее в коде. Тупо мой пример при работе с бинарным протоколом UBX GPS-приемников фирмы u-blox, для примера:
в) Передача пакета выглядит примерно так, опять для примера:
г) Прием. все спать, спать, завтра продолжу.