Forum

How to send values higher than 256 to arduino?

Hello,
is there a way to send values higher than 256 (or more than 256 different values) to arduino via RS232? As I understand it, all values are changed into ascii and ascii is limited to 255 characters. Is that right?

I want to run a stepmotor with a rotary encoder of TouchOSC.
In vvvv I receive a position Value of the TouchOSC encoder and send this Position to Arduino. Everything works well until I reach value 255: In vvvv the next value is 256, 257, 258 but arduino jumps back to 0,1,2 and the Motor turns back to Position 0,1,2.

Do you have any idea how to solve this Problem?

Thanks for your help.

Gerrit

hi gerrit, you are obliged to pass by keywords type protocols, in other words, instead of sending bytes arrays of values:
120{230]…

you will send words (string):

MYVALUE/102345/

whereMYV… are bytes ;-)

Hey karistouf,
thanks for the quick response. To be honest, I don’t understand anything of what you said - i am quite new to vvvv…

I just want to send one changing value (which i have in vvvv) to arduino. As far as I understand, this is done via ASCII Code by the SpellValue Node. That means every value between 0 and 255 is assigned to an ASCII Character and sent to Arduino via the RS232 Node.

But if vvvv sends the Value 256, it is assigned to the ASCII Character of 0 (because in ASCII Code there are only 8 bits = values from 0-255). If vvvv sends 257, it is assigned to ASCII Character of 1. If vvvv sends 258, it is assigned to ASCII Character of 2. And so on.

I don’t understand how i can use words / strings to avoid this.
Could you explain a little more? That would be great.

Thanks a lot,
Gerrit

hi gerrit.

the text you type in your post is ascii caracter, with a value from 0 to 255.

The thing you are sending to arduino is TEXT , asci caracters.

here: http://www.asciitable.com/
you can see letter a is decimal value 97
letter s is decimal value 115
this is not the most girly ascii table, but this will surely help you to understand

what you need to understand is that we are sending bytes and values that will be always from 0 to 255.this for arduino, for internet, for anything. its one of the commonest value ( and some how lower), the byte.

when you are looping out of the bounds ( 257 becames 2) its normal. you are in limitation of the type of data. you will loop back.

when i m saying Keyword protocol, it s because the Byte sended to arduino cant exceed value 255.
you are obliged to create your own protocol in VVVV and in arduino to code and decode an information that will be more than 0-255 range.

So for a nice protocol you will create a system of keywords and phrases with values. This will be the encoding in VVVV.

And in arduino you will need to decode this protocol of your own.

If you look about OSC you will surely find sketches and patches that will make it. but i really advice you that it will be a real benefit for you to create from scratch all of that, especially if you plan to work a lot with arduino.

About coding:
you will have a string in VVVV ( a caracter chain), composed of a syntax enabling to see keywords:

for example:

/MYPROTOCOL/MYSLIDERIS/245566/

This string is in fact bytes, shown in letters, each inside bracket is a byte:

[/](/)[M](M)[Y](Y)[P](P).......[5](5)[5](5)[6](6)[6](6)[/](/)

Now shown in values ( decimal), according to the ascii table:

[47](47)[77](77)[89](89)[80](80).......[53](53)[53](53)[54](54)[54](54)[47](47)

So whats there is te real decimal value sended to the arduino.

So, principle is:

transform Strings of keywords and value in a caracter chains. This caracters will be sended to the arduino thruth rs232 node

Now, its where its become tricky, in arduino you will have tp write your own sketch able to decode your data:

You will need a string comparison ( with wstring, included inside the arduino software), to compare and find if your keywords are presents:

The two keywords with slash ( notice we are using slash to begin and close a data)
/MYPROTOCOL/MYSLIDERIS/
then the value, ended by /:
245566/

If your keywords are present and a slash is ending, you can process extraction of you data inside the arduino.

Thats how you can have values biggers than 255, or use float values ( wich are VVVV’s everywhere)

Voilà !

just a quick sketch, no idea if it works, don’t even have an arduino to test, but maybe it helps.

EDIT: of course this assumes that you know how to interpret those two bytes on the arduino board. http://en.wikipedia.org/wiki/Endianness pops up in my mind for example…

encode_integer_in_16_bit.v4p (5.4 kB)

Radix for ever… see Uncle kalle 16 bits modules, this wiki is too hororfully complex for beginners ;-)

Elias’ patch probably does the same, but Kalle also has a couple of modules which combine two 8bit values (ie 256 steps) into one 16bit value (65536 steps!)

the’re called dmx 16bit something or other

Even if this is a solution for now, you’d still be well off trying to figure out what Karistouf is telling ya ;)

Wow thank you very very much. That helped a lot!

hi gerrit, if you are only in need of integers ( more than 255 values, and not float), you can easely use 16 bits as ellias and mrboni ( nice to read you ) suggested:

the two first bytes will be your first value, the bytes 3 and 4 your second value etc…

This could work and will be more quicker than decoding keyword stuff. Its a way i have half taken with my whitecat. The fact is that RS232 communication with arduino needs something saying the packect is completeley received to be interpreted by arduino, and the buffer to be flushed.
because arduino runs at one speed and computer runs at another speed, you need for the arduino to say: ok i have all the message. Otherwise, you can read but your data will be all mixed up ( yes… ).

Im linking you here what i m coding with arduino, its a little, simple bastard way to do it, mixing keyword and bytes.
http://www.le-chat-noir-numerique.fr/whitecat/dokuwiki/doku.php?id=configuration_arduino_eng#dialog_between_white_cat_arduino

here is the sketch used for this protocol:

//chaine des ordres venant de whitecat
- define maxLength 36
String inString = String(maxLength);   

int threshold_analog=0;
//definitions paramètres com:
const int BAUDRATE=9600;//9600 pour 13 IO et 6 ANA ok //11400 pour 54 IO
//11400 ppour 54 IO
//définitions du nombre de capteurs ( doit concorder aussi dans whitecat -> arduino cfg)
const int NBR_ANALOG=4;
const int NBR_DIGITAL=13;


//création d'un tableau de définition pour les I/O 
boolean digital_is_output[NBR_DIGITAL](NBR_DIGITAL);
boolean allow_analog_read[NBR_ANALOG](NBR_ANALOG);
boolean allow_pwm_write[NBR_DIGITAL](NBR_DIGITAL);
////////////////////////////////////////////////////
//tableaux de stockage des valeurs reçues en input
byte buffer_analog[NBR_ANALOG](NBR_ANALOG);
byte old_buffer_analog[NBR_ANALOG](NBR_ANALOG);
byte buffer_digital[NBR_DIGITAL](NBR_DIGITAL);
byte old_buffer_digital[NBR_DIGITAL](NBR_DIGITAL);
byte valeur_pwm[NBR_DIGITAL](NBR_DIGITAL);

/////////////////////////////////////////////////////////////////
void setup()
{
  Serial.begin(BAUDRATE);
  inString = "";      // remet le buffer à 0

  // initialisation des pin digitals en entrée (haute impédance...)
  for (int i =2; i<NBR_DIGITAL; i++){
    digital_is_output[i](i)=0;
    pinMode(i,INPUT); 
 digital_is_output[i](i)=0;   
    allow_pwm_write[i](i)=0;
  }
  

  /*autorisation de lecture des analogues. Si vous ne définnissez pas =1 l'analogue ne
   sera pas envoyé à WhiteCat*/
  allow_analog_read[0](0)=1;
  allow_analog_read[1](1)=1;
  allow_analog_read[2](2)=1;
  allow_analog_read[3](3)=1;
  allow_analog_read[4](4)=1;
  allow_analog_read[5](5)=1;
  ////////////////////////

  //INITIALISATION DES ON/OFF sur la carte
  for(int i=2; i<NBR_DIGITAL; i++){
    digital_is_output[i](i) ? pinMode(i,OUTPUT): pinMode(i,INPUT);
  }
}

/////////////////////////////////////////////////////////////////
void loop()
{
  while(Serial.available() > 0) {
    char inChar=Serial.read(); // lire caractere
    if(inChar!='\0'){    // un caractere nul marque la fin d'un ordre...
      (inString.length() <maxLength) ? inString+=inChar : inString = inChar;  // vérifie taille max du buffer de réception
    } 
    else {
      if (inString.length() >= 3){   // reçu 0, fin d'un ordre, on décode
        read_order();
        break;
      }
      else {
        inString = "";    // on a recu une fin d'ordre, mais moins de 2 caractères, purge le buffer
      }
    }
  }
}
/////////////////////////////////////////////////////////////
void read_order()
{
// les trois premiers caractères déterminent l'ordre...
  String WCcde = inString.substring(0,3);    // commande whitecat
  if (WCcde == "SD/"){
    arduino_to_whitecat();//lecture des IO et analogs IN et envoi à whitecat
  }
  else if(WCcde == "DO/"){
    whitecat_to_dig();//envoi par white cat des IO
  }
  else if(WCcde == "PW/"){
    whitecat_to_pwm();//envoi par whitecat des pwm
  } 
  inString="";//nettoyage de l'ordre
}
///////////////////////////////////////////////////////////////////////
void whitecat_to_dig()
{
  for(int i=2; i<NBR_DIGITAL; i++)
  {
    if(digital_is_output[i](i)==1 &&  allow_pwm_write[i](i)==0)
    {                            //32= valeur 0
      if(inString[i+3](i+3)!=32){
        digitalWrite(i,HIGH);
      } 
      else {
        digitalWrite(i,LOW);
      }
    }
  }
}
//////////////////////////////////////////////////////////////////////
void whitecat_to_pwm()
{
  for(int i=2; i<NBR_DIGITAL; i++)    // saute les 2 premiers tx/rx ...
  {
    if(allow_pwm_write[i](i)==1)
    {
      valeur_pwm[i](i)=byte(inString[i+5](i+5)-1);    // attention, caracteres PW/, puis 2 premiers canaux tx/rx, puis valeurs valides !!
 analogWrite(i,valeur_pwm[i](i));
    }

  }
}
//////////////////////////////////////////////////////////////////////
void arduino_to_whitecat()
{
  //digitales///////////////////
  bool change_on_dig=0;
  for(int i=2;i<NBR_DIGITAL;i++)//on zappe les états de TX RX en pins 0 et 1
  {
    old_buffer_digital[i](i)=buffer_digital[i](i);
    //si le digital est une entrée
    if(digital_is_output[i](i)==0 && allow_pwm_write[i](i)==0)
    {
      buffer_digital[i](i)= digitalRead(i);
      if(old_buffer_digital[i](i)!=buffer_digital[i](i))
      {
        change_on_dig=1; 
      } 
    }
  }

  //analogues////////////////////
  for(int i=0;i<4;i++){  // on vérifie qu'il n'y a pas de valeur 0
    if(buffer_analog[i](i) == 0)buffer_analog[i](i)=1;
  }


  bool change_on_ang=0;
  for(int i=0;i<NBR_ANALOG;i++)
  {
    old_buffer_analog[i](i)=buffer_analog[i](i); 
    if(allow_analog_read[i](i)==1)//si on autorise la lecture de cet analog
    {
      int temp_val=analogRead(i); 
      if((temp_val/4)>old_buffer_analog[| (temp_val/4)<old_buffer_analog[i](i](| (temp_val/4)<old_buffer_analog[i](i)+threshold_analog )-threshold_analog)
      {
        buffer_analog[i](i)=byte(temp_val/4);
        change_on_ang=1;
      }
    }  
  }
  
  
  //envois
  if(change_on_dig==1)
  {
    Serial.print("DG/");
    Serial.write(buffer_digital,NBR_DIGITAL);
    Serial.println("");
  }
  if(change_on_ang==1)
  {
    Serial.print("AN/");
    Serial.write(buffer_analog,NBR_ANALOG);
    Serial.println(""); 
  } 
}
/////////////////////////////////////////////////////////////////////////

maybe it could inspire you.

Hey karistouf,
thanks for the code. I could solve my problem with radix but i am shure in future projects your code will be useful!

Gerrit