Arduino and Raspberry Pi Serial communication + multiple variables - serial-port

I have a raspberry pi and an arduino. So far I have been able to have the Pi send data to the arduino using serial communication, however it only send one variable and I have multiple variables(2) that I want to send to the arduino (x,y coordinates). Does anyone know if this is possible. I want the first number that is sent from the pi to be the x and the second one the y and the next one the x of the next coord ect.
I have tried editing the code that I use to send one variable but it doesn't work.
Any help would be awesome

Consider the following method to send 2 variable at the same time:
int xpos, ypos;
char x_tx_buffer[20], y_tx_buffer[20];
char x_dummy_buffer[20];
char y_dummy_buffer[20];
char *p_x_tx_buffer, *p_y_tx_buffer;
sprintf(x_dummy_buffer,"%d", xposs);
sprintf(y_dummy_buffer,"%d", yposs);
p_x_tx_buffer = &x_tx_buffer[0];
*p_x_tx_buffer++ = x_dummy_buffer[0];
*p_x_tx_buffer++ = x_dummy_buffer[1];
*p_x_tx_buffer++ = x_dummy_buffer[2];
*p_x_tx_buffer++ = x_dummy_buffer[3];
p_y_tx_buffer = &y_tx_buffer[0];
*p_y_tx_buffer++ = y_dummy_buffer[0];
*p_y_tx_buffer++ = y_dummy_buffer[1];
*p_y_tx_buffer++ = y_dummy_buffer[2];
*p_y_tx_buffer++ = y_dummy_buffer[3];
uart0_filestream = open("/dev/ttyAMA0", O_RDWR | O_NOCTTY | O_NDELAY); //Open in non blocking read/write mode
if (uart0_filestream == -1)
{
//ERROR - CAN'T OPEN SERIAL PORT
printf("Error - Unable to open UART. Ensure it is not in use by another application\n");
}
if (uart0_filestream != -1)
{
int countx = write(uart0_filestream, &x_tx_buffer[0], (p_x_tx_buffer - &x_tx_buffer[0])); //Filestream, bytes to write, number of bytes to write
int county = write(uart0_filestream, &y_tx_buffer[0], (p_y_tx_buffer - &y_tx_buffer[0])); //Filestream, bytes to write, number of bytes to write
if (countx < 0 || county < 0)
{
printf("UART TX error\n");
}
}
close(uart0_filestream);
You can send a max of 8 bytes at a time. Keep that in mind and with that you can modify the about code to send your x and y values in the same uart0_filestream.
Good luck.

Related

Read SerialPort RealTime in HighSpeed Mode

I work on serial Port to read data. serial port's baud-rate is 921600 bps and i use these code to read data:
while(true)
{
bytesToRead = sensor.BytesToRead;
if (bytesToRead > 0)
{
byte[] input = new byte[bytesToRead];
sensor.Read(input, 0, bytesToRead);
}
}
sending protocols is like this. (five digit numbers in bytes + \n\r )
48 48 49 52 50 10 13 , ....
that means : "00142\n\r" -> 00142 -> 142
in each loop I read 4096 bytes of data and i looking for fast way to read all numbers in buffer. i use readLine() function also but it is too slow and some data has been lost.
is there any idea what shroud i do?
thanks.

Why does this binary math fail when adding 00000001, but work correctly otherwise?

I've tried everything I can think of and cannot seem to get the below binary math logic to work. Not sure why this is failing but probably indicates my misunderstanding of binary math or C. The ultimate intent is to store large integers (unsigned long) directly to an 8-bit FRAM memory module as 4-byte words so that a micro-controller (Arduino) can recover the values after a power failure. Thus the unsigned long has to be assembled from its four byte words parts as it's pulled from memory, and the arithmetic of assembling these word bytes is not working correctly.
In the below snippet of code, the long value is defined as four bytes A, B, C, and D (simulating being pulled form four 8-bit memory blocks), which get translated to decimal notation to be used as an unsigned long in the arrangement DDDDDDDDCCCCCCCCBBBBBBBBAAAAAAAA. If A < 256 and B, C, D all == 0, the math works correctly. The math also works correctly for any values of B, C, and D if A == 0. But if B, C, or D > 0 and A == 1, the 1 value of A is not added during the arithmetic. A value of 2 works, but not a value of 1. Is there any reason for this? Or am I doing binary math wrong? Is this a known issue that needs a workaround?
// ---- FUNCTIONS
unsigned long fourByte_word_toDecimal(uint8_t byte0 = B00000000, uint8_t byte1 = B00000000, uint8_t byte2 = B00000000, uint8_t byte3 = B00000000){
return (byte0 + (byte1 * 256) + (byte2 * pow(256, 2)) + (byte3 * pow(256, 3)));
}
// ---- MAIN
void setup() {
Serial.begin(9600);
uint8_t addressAval = B00000001;
uint8_t addressBval = B00000001;
uint8_t addressCval = B00000001;
uint8_t addressDval = B00000001;
uint8_t addressValArray[4];
addressValArray[0] = addressAval;
addressValArray[1] = addressBval;
addressValArray[2] = addressCval;
addressValArray[3] = addressDval;
unsigned long decimalVal = fourByte_word_toDecimal(addressValArray[0], addressValArray[1], addressValArray[2], addressValArray[3]);
// Print out resulting decimal value
Serial.println(decimalVal);
}
In the code above, the binary value should result as 00000001000000010000000100000001, AKA a decimal value of 16843009. But the code evaluates the decimal value to 16843008. Changing the value of addressAval to 00000000 also evaluates (correctly) to 16843008, and changing addressAval to 00000010 also correctly evaluates to 16843010.
I'm stumped.
The problem is that you're using pow(). This is causing everything to be calculated as a binary32, which doesn't have enough precision to hold 16843009.
>>> numpy.float32(16843009)
16843008.0
The fix is to use integers, specifically 65536 and 16777216UL.
Do not use pow() for this.
The usual way to do this is with the shift operator:
uint32_t result = uint32_t(byte3 << 24 | byte2 << 16 | byte1 << 8 | byte0);

Arduino Serial.ParseInt() Alternative

I need to read in exactly 1 three digit integer (example: 134) from the serial monitor. I am currently using Serial.parseInt() and getting the behavior I want, but it is very slow. What would be a faster alternative to this method?
Edit: All parts of the integer must be read in at the same time, so using Serial.available() and Serial.read() is not an option.
Edit2: I attempted using
while (Serial.available()) {
int val = Serial.read();
int val2 = Serial.read();
int val3 = Serial.read();
Serial.print("Val1: ");
Serial.println(val);
Serial.print("Val2: ");
Serial.println(val2);
Serial.print("Val3: ");
Serial.println(val3);
}
In the loop portion, but got the output
Val1: 97
Val2: -1
Val3: -1
Val1: 98
Val2: -1
Val3: -1
Val1: 99
Val2: -1
Val3: -1
when I typed abc into the serial monitor.
It's okay to use Serial.parseInt.
For me, in my setup function
//this will allow the parseInt to read faster and
//the arduino board will responsd faster
Serial.setTimeout(50);
This is because parseInt() will continue to read from serial until either
it reaches a non-integer value e.g. alphabet, or
the serial timeouts.

ADC transfer function

I took over the project from someone who had gone a long time ago.
I am now looking at ADC modules, but I don't get what the codes mean by.
MCU: LM3S9B96
ADC: AD7609 ( 18bit/8 channel)
Instrumentation Amp : INA114
Process: Reading volts(0 ~ +10v) --> Amplifier(INA114) --> AD7609.
Here is codes for that:
After complete conversion of 8 channels which stored in data[9]
Convert data to micro volts??
//convert to microvolts and store the readings
// unsigned long temp[], data[]
temp[0] = ((data[0]<<2)& 0x3FFFC) + ((data[1]>>14)& 0x0003);
temp[1] = ((data[1]<<4)& 0x3FFF0) + ((data[2]>>12)& 0x000F);
temp[2] = ((data[2]<<6)& 0x3FFC0) + ((data[3]>>10)& 0x003F);
temp[3] = ((data[3]<<8)& 0x3FF00) + ((data[4]>>8)& 0x00FF);
temp[4] = ((data[4]<<10)& 0x3FC00) + ((data[5]>>6)& 0x03FF);
temp[5] = ((data[5]<<12) & 0x3F000) + ((data[6]>>4)& 0x0FFF);
temp[6] = ((data[6]<<14)& 0x3FFF0) + ((data[7]>>2)& 0x3FFF);
temp[7] = ((data[7]<<16)& 0x3FFFC) + (data[8]& 0xFFFF);
I don't get what these codes are doing...? I know it shifts but how they become micro data format?
transfer function
//store the final value in the raw data array adstor[]
adstor[i] = (signed long)(((temp[i]*2000)/131072)*10000);
131072 = 2^(18-1) but I don't know where other values come from
AD7609 datasheet says The FSR for the AD7609 is 40 V for the ±10 V range and 20 V for the ±5 V range, so I guessed he chose 20vdescribed in the above and it somehow turned to be 2000???
Does anyone have any clues??
Thanks
-------------------Updated question from here ---------------------
I don't get how 18bit concatenated value of data[0] + 16bit concatenated value of data[1] turn to be microvolt after ADC transfer function.
data[9]
+---+---+--- +---+---+---+---+---+---++---+---+---++---+---+---++
analog volts | 1.902v | 1.921v | 1.887v | 1.934v |
+-----------++-----------+------------+------------+------------+
digital value| 12,464 | 12,589 | 12,366 | 12,674 |
+---+---+---++---+---+---++---+---+---++---+---+---++---+---+---+
I just make an example from data[3:0]
1 resolution = 20v/2^17-1 = 152.59 uV/bit and 1.902v/152.59uv = 12,464
Now get thru concatenation:
temp[0] = ((data[0]<<2)& 0x3FFFC) + ((data[1]>>14)& 0x0003) = C2C0
temp[1] = ((data[1]<<4)& 0x3FFF0) + ((data[2]>>12)& 0x000F) = 312D3
temp[2] = ((data[1]<<6)& 0x3FFC0) + ((data[3]>>10)& 0x003F) = 138C
Then put those into transfer function and get microvolts
adstor[i] = (signed long)(((temp[i]*2000)/131072)*10000);
adstor[0]= 7,607,421 with temp[0] !=1.902*e6
adstor[1]= 30,735,321 with temp[1] != 1.921*e6
adstor[2]= 763,549 with temp[2]
As you notice, they are quite different from the analog value in table.
I don't understand why data need to bit-shifting and <<,>> and added up with two data[]??
Thanks,
Please note that the maximum 18-bit value is 2^18-1 = $3FFFF = 262143
For [2] it appears that s/he splits 18-bit word concatenated values into longs for easier manipulation by step [3].
[3]: Regarding adstor[i] = (signed long)(((temp[i]*2000)/131072)*10000);
To convert from raw A/D reading to volts s/he multiplies with the expected volts and divides by the maximum possible A/D value (in this case, $3FFFF) so there seems to be an error in the code as s/he divides by 2^17-1 and not 2^18-1. Another possibility is s/he uses half the range of the A/D and compensates for that this way.
If you want 20V to become microvolts you need to multiply it by 1e6. But to avoid overflow of the long s/he splits the multiplication into two parts (*2000 and *10000). Because of the intermediate division the number gets small enough to be multiplied at the end by 10000 without overflowing at the expense of possibly losing some least significant bit(s) of the result.
P.S. (I use $ as equivalent to 0x due to many years of habit in certain assembly languages)

pointer * and & difference

I am confused on pointers in objective-c. I wrote a very simple program to try and understand
char* temp = "temp";
printf("temp - %s \n", temp);
printf("*temp - %d \n", *temp);
printf("&temp - %s \n", &temp);
printf("&(*temp) - %s \n", &(*temp));
In this example, temp is a pointer to char with a default value of "temp". What does *temp, &temp mean? The output is:
temp - temp
*temp - 116
&temp - 00#
&(*temp) - temp
So temp is the pointer. When I print temp, it prints the value "temp". *temp is the value of the pointer or the address of the variable it points to. What is &temp? Is this the address of the pointer itself?
I wrote a second program in which I assign pointer to address of n (&n).
int n = 50, x;
int *ptr;
ptr = &n;
x = *ptr;
printf("n - %d\n", n);
printf("ptr - %d\n", ptr);
printf("*ptr - %d\n", *ptr);
printf("x - %d\n", x);
The output is:
n - 50
ptr - 2271924
*ptr - 50
x - 50
n is 50 and x is undefined. ptr points to address of n. Why does *ptr print 50 and *temp prints 116? Is the difference between how I have defined the two pointers? I am trying to understand the basics. Thank you.
When we print out *temp, we go to the temp variable, locate the address that it holds (the one it points to), than print out whatever data is in that location.
When we print out &temp, we are asking for the address of the temp variable, not what it is pointing to.
For your second program, you assign the address of n (using &) to ptr. This way, when we choose to call *ptr, it's gonna locate the address stored in ptr (which is n's), and print out whatever n holds. So you then assigned the value *ptr points to, and store it in x.
In summary, when declaring a pointer, & will print out the address of the variable, * will print out what it points to, and nothing in front will print out the address of the variable it's pointing to.

Resources