Basic data question

Hi.

Im sending data from max/msp (pure data) to Teensy 4.0 board (programmed with Arduino IDE) and back.

Im not clear about the different types of data transfer.

I send directly numbers from 0 to 255 and I get them back but above that not response.

I know it has something to do with bits...
I thought serial was done in ascii......
I know my knoledge is limited...please be gentle.

char receivedChar;
boolean newData = false;

void setup() {
 Serial.begin(9600);
 Serial.println("<Arduino is ready>");
}

void loop() {
 recvOneChar();
 showNewData();
}

void recvOneChar() {
 if (Serial.available() > 0) {
 receivedChar = Serial.read();
 newData = true;
 }
}

void showNewData() {
 if (newData == true) {
 Serial.write (receivedChar);
 newData = false;
 }
}

So I don't have to Google it, what is max/msp?

By the way, ASCII is a 7 bit code that has been extended to 8 bits. Therefore the greatest valued character is 255. Does that click somewhere?

reduces to:

void loop() {
 if (Serial.available() > 0) {
 receivedChar = Serial.read();
 Serial.write (receivedChar);
 }
}

what is the question?
you code simply echoes the byte it receives back to the sender

void loop() {
    if (Serial.available() > 0)
        Serial.write (Serial.read());
}

all data is bits: graphics, letters (ascii), integers.
a byte is 8-bits

ascii

Check out the SerialTransfer library that supports sending any arbitrary data.

So I don't have to Google it, what is max/msp?

It is a modular programing language from Cycling 74. I use it in Ableton Live ( digital audio workstation) to comunicate with hardware.
Im biulding a cotroller with Adafruits Neotrellis led/button boards with a Teensy 4.0 controller board.

To make my question clearer.
I need to send integers from 0 to 600 to teensy. And sending directly the int to serial (in max/msp) I could only do 0-255.

Using a different code, with end marker, and playing around with " atoi" and "itoa" I managed to solve that obstacle.
But since I dont understand the different data types and convertions I have a, hopefully, last and more concrete obstacle.

On max/msp , I convert a number (lets say 512) to asccii, append a 10 (endline) at the end and send it to serial module.

On teensy I think I get an array but I need to use integers and cant do the convertion.

Here the code


const byte numChars = 32;
char receivedChars[numChars];          
boolean newData = false; 
unsigned long  a; 


void loop() {
 recvWithEndMarker();
 showNewData();
}

void recvWithEndMarker() {
 static byte ndx = 0;
 char endMarker = '\n';
 char rc;
 
           while (Serial.available() > 0 && newData == false) {
 rc = Serial.read();

 if (rc != endMarker) {
 receivedChars[ndx] = rc;
 ndx++;
 if (ndx >= numChars) {
 ndx = numChars - 1;
 }
 }
 else {
 receivedChars[ndx] = '\0'; 
 ndx = 0;
 newData = true;
 }
 }
}

void showNewData() {
 if (newData == true) {
       
    if (receivedChars == 512 ) {
       a =  0x000000;     
    }

    else if (receivedChars == 513 ) {  
       a =  0x006600;
    }

    else if (receivedChars == 514 ) {
    trellis.show();
    }
 
    else {
    trellis.setPixelColor(receivedChars , a);     
    } 
  newData = false;
  }
}

Here is the error I get

Nuevito: In function 'void showNewData()':
C:\Users\Moris\Desktop\Nuevito\Nuevito.ino:104:26: warning: ISO C++ forbids comparison between pointer and integer [-fpermissive]
     if (receivedChars == 512 ) {
                          ^
C:\Users\Moris\Desktop\Nuevito\Nuevito.ino:108:31: warning: ISO C++ forbids comparison between pointer and integer [-fpermissive]
     else if (receivedChars == 513 ) {  
                               ^
C:\Users\Moris\Desktop\Nuevito\Nuevito.ino:112:31: warning: ISO C++ forbids comparison between pointer and integer [-fpermissive]
     else if (receivedChars == 514 ) {
                               ^
C:\Users\Moris\Desktop\Nuevito\Nuevito.ino:117:44: warning: invalid conversion from 'char*' to 'uint16_t {aka short unsigned int}' [-fpermissive]
     trellis.setPixelColor(receivedChars , a);     
                                            ^
In file included from C:\Users\Moris\Desktop\Nuevito\Nuevito.ino:1:0:
C:\Users\Moris\Documents\Arduino\libraries\Adafruit_seesaw_Library/Adafruit_NeoTrellis.h:82:8: note:   initializing argument 1 of 'void Adafruit_MultiTrellis::setPixelColor(uint16_t, uint32_t)'
   void setPixelColor(uint16_t num, uint32_t color);
        ^

Since your reciving code is from this turorial: Serial Input Basics - updated look at example #4 to see how to receive numbers rather than text

you could send a value of 600 as 2 bytes. but now you need a way to delimit those bytes from others being sent

another approach is to simply send the value as an ascii string with a recognizable line termination such as '\n' using readBytesUntil(), for example. the teensy then needs to translate the string to an integer using atoi(), for example

consider
bear in mind, an integer variable is being printed, not the received c-string

char s [80];

int val;

void loop() {
    if (Serial.available())  {
        int n = Serial.readBytesUntil ('\n', s, sizeof(s));
        s [n] = 0;

        val = atoi (s);
        Serial.println (val);
    }
}

void setup() {
    Serial.begin(9600);
}

This will work as long as the message itself never contains newlines. A more robust choice could be 0x03 (end of text) or 0x04 (end of transmission), to stick with the ASCII standard.

Since your reciving code is from this turorial: Serial Input Basics - updated look at example #4 to see how to receive numbers rather than text

Yes!!. That did it for me. Send in ascii and then atoi convertion.

Last question.

Would be any noticeable difference in overall speed if instead of doing it this way I send 2 bytes?

int number;
const byte numChars = 32;
char receivedChars[numChars];          
boolean newData = false; 
unsigned long  a; 
int dataNumber = 0;  


void loop() {
 recvWithEndMarker();
 showNewData();
}

void recvWithEndMarker() {
 static byte ndx = 0;
 char endMarker = '\n';
 char rc;
 
 
           while (Serial.available() > 0 && newData == false) {
 rc = Serial.read();

 if (rc != endMarker) {
 receivedChars[ndx] = rc;
 ndx++;
 if (ndx >= numChars) {
 ndx = numChars - 1;
 }
 }
 else {
 receivedChars[ndx] = '\0'; 
 ndx = 0;
 newData = true;
 }
 }
}

void showNewData() {
 if (newData == true) {
       
    dataNumber = 0;
    dataNumber = atoi(receivedChars);
    
    if (dataNumber == 512 ) {
       a =  0x000000;     
    }

    else if (dataNumber == 513 ) {  
       a =  0x006600;
    }

    else if (dataNumber == 514 ) {
    trellis.show();
    }
 
    else {
    trellis.setPixelColor(dataNumber , a);     
    } 
  newData = false;
  }
}

I am not sure what you mean by this. Which 2 bytes? Just the number itself in binary (MSB then LSB)?
Receiving 2 bytes will always be faster than receiving 4 bytes [e.g."512\n"] but you then have the issue of figuring out if you get out of sync and start receiving LSB then MSB which means you need some sort of marker again and since you are receiving binary, you could theoretically receive any value 0x00 - 0xFF so there is no safe marker to use.

IF speed is really an issue, you can always bump your baud rate to 115200 or higher

instead of your recWithEndMarker(), see readBytesUntil() and it's use in the code posted in #9

Questions....said Roy Batty to the chinese eye designer..

 if (Serial.available())  {
        int n = Serial.readBytesUntil ('\n', s, sizeof(s));
        s [n] = 0;

Would it be ok to put a 2 in place of "sizeof(s)" ? Since I only need 2 bytes

I dont understand this line...

int n = Serial.readBytesUntil ('\n', s, sizeof(s));

Why an integer? isnt the data an array? And what is the function of that n

Thank you.

the 3rd argument is the size of the array to insure that it doesn't overflow.

if you're receiving a ascii string, you want to receive the complete string using the terminator, 1st argument, to know when it is complete

if you're receiving an ascii string representing an integer, such as 600, there are 3 ascii bytes. a 16-bit integer can represent a value of 65535, which is 5 ascii characters. atoi() will translate the c-string to a 2 byte integer

it's returning the # of characters received. the received string in the array passed as the 2nd argument.

maybe there's a misunderstanding about sending the data as an ascii c-string. is there?

Hey, unknown human being, thanks for the patience. I appreciate it.

maybe there's a misunderstanding about sending the data as an ascii c-string. is there?

Yes. I think I dont understand how serial comunnication works

If I send up to 255 directly to serial that is 1 byte right?

but if I convert it to ascii before send, that would be 50 53 53, 3 bytes right?

So I was thinking of sending 2 bytes without ascii covertion......

how do you remain synchronized? how do you know which byte is the first byte?

Well. Then it would be instead of 4 bytes (ascii plus marker) 3 bytes (2 bytes plus marker)

what if the marker is the same value as one of the data bytes?

Hahaha...Yeah..

Thank you for this Socratic method you used here..