Arduino Serial.ParseInt() Alternative - serial-port

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.

Related

Bizzare output from Arduinio

I'm trying to do something relatively simple with the Arduino (trying to get some lights to light up like a Simon says game) but I'm getting some really bizarre outputs
I got some really bizarre output on the pins so I took those parts of the code out to see it on a serial monitor to see what the contents of the array that holds the sequence of lights (colors) are. It just really doesn't make sense to me.
What my code is supposed to do is append a random number from 1-4 onto colors[] and then read them back out onto the serial monitor
bool lightValue[4] = { 0 };
// stores whether each LED is lit or not
int buttonPressed;
// 0 - no button pressed / nothing
// 1 - red
// 2 - yellow
// 3 - green
// 4 - blue
int colors[] = { 0 };
// probably not the best name for this variable but oh well
// stores all the colors displayed for the simon says
// refer above to see what each number means
int colorNum = 0;
// again not the best name, stores the number of colors displayed so far
// AKA the length of colors[]
int randomNum;
// will store a random number
// variables
void setup() {
randomSeed(analogRead(0));
Serial.begin(9600);
Serial.println();
Serial.println("PROGRAM START");
}
// pinModes. Lots of pinModes.
void loop() {
randomNum = random(1,5);
colors[colorNum] = randomNum;
Serial.println();
Serial.print(colorNum);
Serial.print(" ");
colorNum++;
// adds another random color onto the end of the color sequence
for (int i = 0; i < colorNum; i++) {
Serial.print(colors[i]);
delay(500);
}
}
Some examples of outputs I got:
0 3
0 1
2 13520
3 145202
4 1552024
5 16520241
6 175202414
7 1852024141
8 19520241414
9 1105202414141
10 11152024141414
0 1
2 13520
3 145202
4 1552024
5 16520241
6 175202414
7 1852024141
8 19520241414
9 1105202414141
10 11152024141414
colorNum, the main increment of this loop for some reason skips over one. The first and second output do not match, the third item in the array is 520, and for some reason, the second item is incrementing by 1 every step. Also, it stops at 10 for some reason.
The only thing I could chalk this inconsistent behavior to is accessing some piece of memory where it shouldn't, but I can't come up for the life of me where I horribly messed up.
int colors[] = { 0 };
defines an integer array with a single element 0.
Here colors[colorNum] = randomNum; you're assigning numbers to indices outside of that array for colorNum > 0. You shouldn't do that. This memory region is not reserved for colors!
So who stops your compiler from storing colorNum right after colors?
So when you assing a value to colors[1] you could very well change the value of colorNum. Same for your loop control variable i.
So the second value is incremented because you're incrementing colorNum which is at the same memory location as colorNum[1].
The print for colorNum == 1 is missing because you assigned 5 to colors[2] which is at the same memory location as your loop control variable i. As 5 > colorNum the loop does not run.
I just did this on a 32bit C++ compiler:
int colors[] = {0};
int colorNum = 0;
int i = 0;
And the addresses printed:
colors[0] # 0x7fff029a5ac4
colorNum # 0x7fff029a5ac8
colors[1] # 0x7fff029a5ac8
i # 0x7fff029a5acc
colors[2] # 0x7fff029a5acc
Note that colorNum is just 4 bytes after colors[0] which is the same address as colors[1]!
Anyway you shouldn't just fill memory in an infinite loop in the first place.
You're on a micro controller where memory is a limited resource

Data loss via serial port (RS232)

I am trying to read a series of data via serial port. Below are my test scenarios:
I have a sender (POS terminal) and a receiver (dll) on windows 10. Both connected via RS232 cable (9 pins).
The sender writes 16 bytes of data at one time. The receiver is able to read the data, 1 byte per read, by looping 16 times.
The sender writes 114 bytes of data at one time. The receiver is able to read the data , 1 byte per read, by looping 114 times.
The sender writes 115 bytes of data at one time. The receiver is able to read the data, 1 byte per read, by looping 115 times. But the last character is lost. In other words, the last character seems to be corrupted.
E.g. Data written: ABCDEFGHIJKLMNOPQRSTABCDEFGHIJKLMNOPQRSTABCDEFGHIJKLMNOPQRSTABCDEFGHIJKLMNOPQRSTABCDEFGHIJKLMNOPQRSTABCDEFGHIJKLMNO
I am able to get "ABCDEFGHIJKLMNOPQRSTABCDEFGHIJKLMNOPQRSTABCDEFGHIJKLMNOPQRSTABCDEFGHIJKLMNOPQRSTABCDEFGHIJKLMNOPQRSTABCDEFGHIJKLMN" correctly. But the last character 'O' is corrupted. Instead the data read in place of last character is (ASCII value) 205, 255, 234 etc. The data is not consistent during multiple read attempts.
Can anyone please put some light on this? Can anyone guide me if I am missing something-somewhere?
I referred this article for my project: Serial Port Communication
Below is the code snippet:
//Port opening.
HANDLE hPortDailUp = CreateFile(portfinal,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_ALWAYS,
0,
NULL);
//Setting COM timeouts.
SetCommMask(hPortDailUp, 0);
SetupComm(hPortDailUp, 2048, 2048);
GetCommTimeouts (hPortDailUp, &commTimeOuts);
commTimeOuts.ReadIntervalTimeout = 100;
commTimeOuts.ReadTotalTimeoutMultiplier = 70;
commTimeOuts.ReadTotalTimeoutConstant = 1000; //1000
commTimeOuts.WriteTotalTimeoutMultiplier = 0;
commTimeOuts.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(hPortDailUp, &commTimeOuts);
//Setting port configuration.
DCB PortDCB;
PortDCB.DCBlength = sizeof(DCB);
PortDCB.BaudRate = BaudRate;
PortDCB.ByteSize = 8;
PortDCB.Parity = NOPARITY;
PortDCB.StopBits = ONESTOPBIT;
PortDCB.fOutxCtsFlow = RTS_CONTROL_DISABLE;
PortDCB.fRtsControl = RTS_CONTROL_DISABLE;
SetCommState(hPortDailUp, &PortDCB)
//Reading data from serial port.
unsigned char tempRecvBuf[3001] = {'\0'};
ReadFile(hPortDailUp, tempRecvBuf + nBytesRead, 1, &TempLen, NULL);
//PortDCB Value at runtime.
PortDCB {DCBlength=28 BaudRate=115200 fBinary=1 ...} _DCB
DCBlength 28 unsigned long
BaudRate 115200 unsigned long
fBinary 1 unsigned long
fParity 0 unsigned long
fOutxCtsFlow 0 unsigned long
fOutxDsrFlow 0 unsigned long
fDtrControl 1 unsigned long
fDsrSensitivity 0 unsigned long
fTXContinueOnXoff 0 unsigned long
fOutX 0 unsigned long
fInX 0 unsigned long
fErrorChar 0 unsigned long
fNull 0 unsigned long
fRtsControl 0 unsigned long
fAbortOnError 0 unsigned long
fDummy2 0 unsigned long
wReserved 0 unsigned short
XonLim 2048 unsigned short
XoffLim 512 unsigned short
ByteSize 8 '\b' unsigned char
Parity 0 '\0' unsigned char
StopBits 0 '\0' unsigned char
XonChar 17 '\x11' char
XoffChar 19 '\x13' char
ErrorChar 0 '\0' char
EofChar 0 '\0' char
EvtChar 0 '\0' char
wReserved1 0 unsigned short
It's possible your loop doesn't get the characters read out quite fast enough, so that by the 115th time, a new character is already overwriting the last one that is being read out too late.
To test this, you can add a very short delay between characters on the transmitter side, then see if the receiver acts differently.

About pointers and ASCII code

im learning more about c language and i have 1 doubt about 1 code that i have seen.
main(){
int i = (65*256+66)*256+67;
int* pi;
char* pc;
pi = &i;
pc = (char*)pi;
printf("%c %c %c \n", *pc, *(pc+1), *(pc+2));
}
Output is: C B A
I know that ASCII code of A is 65, B is 66, and C is 67 but the variable i is none of them.
If i put variable i=65, the output is just A and dont show B or C, why?
And i would like to know why this code have that output. Thanks for any help.
The line
int i = (65*256+66)*256+67;
turns i into the following
00000000 01000001 01000010 01000011
int = 4 bytes or 4 groups of 8 bits
char = 1 byte or 1 group of 8 bits.
What happens is that a char pointer is used to point to a subset of the original int bits.
At first the pointer points to the 8 least significant bits (the group to the right).
And the letter C is printed. Then, the pointer it self is incremented by 1 which makes it point to the next group of 8 bits in the memory which happens to be B. And once more for the A.
*256 means left shift by 8 bit (1 byte) so the line
int i = (65*256+66)*256+67;
actually put A,B,C on 3 adjacent bytes in memory
then pi pointer made point to the address of integer i, then same address down cast to char pointer pc, so pc actually hold the address to a byte that contains 'A', and of course if you add 1 and 2 to the address that means the adjacent 'B' and 'C' get pointed to and print out.
EDIT: just to clarify a bit more int is 32 bit long but char is 8 bit, that's why u need a char pointer to represent an address valid for 8 bit long.
Characters are stored as bytes, as you probably know. The initializing of the variable 'i' has the following meaning:
65*256 // store 65 ('A') and left shift it by 8 byte (= '*256')
(65*256+66)*256 // add 66 ('B') and shift the whole thing again
(65*256+66)*256+67 // add 67 ('C')
'pi' is initialized as a INT pointer to 'i'
'pc' is initialized as a CHAR pointer to 'pi'
So 'pc' then holds the address of the beginning of the 3 bytes stored in 'i', which holds 'A'.
By adding 1 and 2 to the address in pc, you get the second and third bytes (containing 'B' and 'C'), as follows:
printf("%c %c %c \n", *pc, *(pc+1), *(pc+2));
Working on the bits here ;D

Referencing individual pins, in Hex, Bit masking

I'm using a netduino plus 2, and need to understand how to convert an individual pins's number into hex for bit masking, eg:
PERSUDO
if counter_value_bit_1 is 1, do:
write 1 to D0 pin
else
write 0 to D0 pin
..... counting from bit_1 through bit_9.
if counter_value_bit_9 is 1, do:
write 1 to D0 pin
else
write 0 to D0 pin
Answer
if (counter_value & 0x01) { //bit_1
...}
if (counter_value & 0x200) { //bit_9
...}
My question: how do you get 0x200 = bit 9, ect?
An example or two for bits in between 1 and 9 would be great.
THANKS
Which language do you use?
In C you cant handle a bit "9" in a portable way, see byte ordering. If you know the byte order you could extract the byte with bit 9.
#define BYTE_WITH_BIT_9 ...
int counter_value = 42;
((char*)counter_value)[BYTE_WITH_BIT_9]
Cast to char* to access the raw bytes. Then chose the byte and now you can do magic bit operations.

Arduino and Raspberry Pi Serial communication + multiple variables

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.

Resources