Serial read doesnt loop well - arrays

it's hard to dertermine a appropriate question for my problem, so hear is what i want:
I have an Arduino Pro Micro and an Arduino Nano 33 BLE. The Nano use his 9axis Sensor to get the Position. I only use the angle of up/down and left/right. He map the angles betwen 21 to 108 and 0 to 100 for a pitch and a volume. I write the Numbers via sprintf in an char array and send it via Serial 1 to the Arduino Pro Micro.
Here i have the Problem. I want to read permanently the sended Array. I use this atm:
void readURAT(){
char buffer[7], inChar;
int i =0;
while(Serial1.available() > 0){
if(i<index){
inChar=Serial1.read();
buffer[i]=inChar;
i++;
}else{
buffer[6]='\0';
i=0;
Serial.println(buffer);
Serial1.flush();
}
}
}
This works but only a few times. It's like, i get the value 10 times and then nothing. The Char Value is for example "066070". Doe's someone have a clue what i missed?
Thanks in advance for the help!

You will get an silent buffer overflow because you loop var i is not checked against the array size (7) of buffer. index is not defined in the function.
if you receive less then index char, your buffer will not have a \0 terminator.

Related

Serial.print attatch a variable unintended

I'm programming an Arduino UNO with a SIM7600CE LTE Shield. I want to track the position and get the Received Signal Strength Indication. I can communicate with the shield and it works great. Now I want to transform the answers to my wanted values. Here is my Code:
void readRSSI(void){
char RecMessage[200]="0";
char s_RSSI[2]="0";
char s_BER[2]="0";
int i_RSSI=0, i_BER=0;
int i =0;
char * pch;
bool answer=false;
//while(myserial.available() == 0);
myserial.write("AT+csq\r");
do{
if(myserial.available() > 0){
RecMessage[i]=myserial.read();
i++;
if (strstr(RecMessage, "OK") != NULL){
answer = true;
}
}
} while (!answer);
myserial.flush();
if(answer){
pch = strstr(RecMessage,",");
int posi = pch - RecMessage;
s_RSSI[0]=RecMessage[posi-2];
s_RSSI[1]=RecMessage[posi-1];
s_BER[0]=RecMessage[posi+1];
s_BER[1]=RecMessage[posi+2];
i_RSSI=atoi(s_RSSI);
i_BER=atoi(s_BER);
}
Serial.flush();
Serial.println("RSSI Info:");
// Serial.println(RecMessage);
Serial.print("Received Signal Strength Indication: ");
Serial.print(i_RSSI);
Serial.print(" and Channel Bit Error Rate: ");
Serial.println(i_BER);
Serial.flush();
return;
}
The RecMessage is something like this:
AT+csq
+CSQ: 31,99
OK
So the Code basicly looks where the ',' is and take the left and the right numbers of it. It kinda works well, but somehow my output is this:
12:03:51.068 -> RSSI Info:
12:03:51.114 -> Received Signal Strength Indication: 31 and Channel Bit Error Rate: 9931
But thats not what it should be ... somehow it put's the i_RSSI at the end of the i_BER. The best Part is, if I comment out the Serial.print(i_RSSI);, it works right, the Serial shows just 99. Can somebody explain what I am missing?.
I'm using the Arduino IDE 1.8.19.
Assuming UART communication with AT commands and similar; then string null terminators are never sent on the bus, but instead CR and/or LF are used as delimiters. So you need to append null terminators manually on things you pick up from the bus. And this must be done before you call C standard lib functions like strstr or strlen which assume that you pass them a null terminated string.

Does Arduino Uno/OSEPP Uno have enough memory to create a servo array?

I'm pretty bad at coding (I know the basics), and I'm trying to create an array of servos in Arduino to control via Serial with Processing. I vaguely remember something about Arduino microcontrollers having really limited memory, so I'm not sure if creating an array of Servo objects would work. Here's the code I have so far:
#include <Servo.h>
Servo[] servos = new Servo[6]; //holds the servo objects
int[] servoPos = {90,112,149,45,75,8}; //holds the current position of each servo
char serialVal; //store the serialValue received from serial
void setup()
{
for(int i = 0; i < servos.length; i++) //attach servos to pins
{
servos[i].attach(i+8);
}
Serial.begin(115200); //initialize serial
}
Would an Arduino Uno board be able to support this array and utilize it like in Java? Before now, I've been creating each object separately, which was very inefficient and time-consuming to type and read.
Also, if there's anything that would stop this code from executing, please tell me. I appreciate your help.
My advice is to fire up your Arduino IDE and give it a try. First off you're going to find that you have some problems in your code:
Your array syntax is incorrect. For example:
int[] servoPos = {90,112,149,45,75,8}; //holds the current position of each servo
should be written:
int servoPos[] = {90,112,149,45,75,8}; //holds the current position of each servo
I guess this servos.length is a Java thing? Instead you should determine that value by:
sizeof(servos) / sizeof(servos[0])
After you get it to compile you'll see a message in the black console window at the bottom of the Arduino IDE window:
Sketch uses 2408 bytes (7%) of program storage space. Maximum is 32256 bytes.
Global variables use 242 bytes (11%) of dynamic memory, leaving 1806 bytes for local variables. Maximum is 2048 bytes.
So that will give you some idea of the memory usage. To check free memory at run time I use this library:
https://github.com/McNeight/MemoryFree

Reading serial port faster

I have a computer software that sends RGB color codes to Arduino using USB. It works fine when they are sent slowly but when tens of them are sent every second it freaks out. What I think happens is that the Arduino serial buffer fills out so quickly that the processor can't handle it the way I'm reading it.
#define INPUT_SIZE 11
void loop() {
if(Serial.available()) {
char input[INPUT_SIZE + 1];
byte size = Serial.readBytes(input, INPUT_SIZE);
input[size] = 0;
int channelNumber = 0;
char* channel = strtok(input, " ");
while(channel != 0) {
color[channelNumber] = atoi(channel);
channel = strtok(0, " ");
channelNumber++;
}
setColor(color);
}
}
For example the computer might send 255 0 123 where the numbers are separated by space. This works fine when the sending interval is slow enough or the buffer is always filled with only one color code, for example 255 255 255 which is 11 bytes (INPUT_SIZE). However if a color code is not 11 bytes long and a second code is sent immediately, the code still reads 11 bytes from the serial buffer and starts combining the colors and messes them up. How do I avoid this but keep it as efficient as possible?
It is not a matter of reading the serial port faster, it is a matter of not reading a fixed block of 11 characters when the input data has variable length.
You are telling it to read until 11 characters are received or the timeout occurs, but if the first group is fewer than 11 characters, and a second group follows immediately there will be no timeout, and you will partially read the second group. You seem to understand that, so I am not sure how you conclude that "reading faster" will help.
Using your existing data encoding of ASCII decimal space delimited triplets, one solution would be to read the input one character at a time until the entire triplet were read, however you could more simply use the Arduino ReadBytesUntil() function:
#define INPUT_SIZE 3
void loop()
{
if (Serial.available())
{
char rgb_str[3][INPUT_SIZE+1] = {{0},{0},{0}};
Serial.readBytesUntil( " ", rgb_str[0], INPUT_SIZE );
Serial.readBytesUntil( " ", rgb_str[1], INPUT_SIZE );
Serial.readBytesUntil( " ", rgb_str[2], INPUT_SIZE );
for( int channelNumber = 0; channelNumber < 3; channelNumber++)
{
color[channelNumber] = atoi(channel);
}
setColor(color);
}
}
Note that this solution does not require the somewhat heavyweight strtok() processing since the Stream class has done the delimiting work for you.
However there is a simpler and even more efficient solution. In your solution you are sending ASCII decimal strings then requiring the Arduino to spend CPU cycles needlessly extracting the fields and converting to integer values, when you could simply send the byte values directly - leaving if necessary the vastly more powerful PC to do any necessary processing to pack the data thus. Then the code might be simply:
void loop()
{
if( Serial.available() )
{
for( int channelNumber = 0; channelNumber < 3; channelNumber++)
{
color[channelNumber] = Serial.Read() ;
}
setColor(color);
}
}
Note that I have not tested any of above code, and the Arduino documentation is lacking in some cases with respect to descriptions of return values for example. You may need to tweak the code somewhat.
Neither of the above solve the synchronisation problem - i.e. when the colour values are streaming, how do you know which is the start of an RGB triplet? You have to rely on getting the first field value and maintaining count and sync thereafter - which is fine until perhaps the Arduino is started after data stream starts, or is reset, or the PC process is terminated and restarted asynchronously. However that was a problem too with your original implementation, so perhaps a problem to be dealt with elsewhere.
First of all, I agree with #Thomas Padron-McCarthy. Sending character string instead of a byte array(11 bytes instead of 3 bytes, and the parsing process) is wouldsimply be waste of resources. On the other hand, the approach you should follow depends on your sender:
Is it periodic or not
Is is fixed size or not
If it's periodic you can check in the time period of the messages. If not, you need to check the messages before the buffer is full.
If you think printable encoding is not suitable for you somehow; In any case i would add an checksum to the message. Let's say you have fixed size message structure:
typedef struct MyMessage
{
// unsigned char id; // id of a message maybe?
unsigned char colors[3]; // or unsigned char r,g,b; //maybe
unsigned char checksum; // more than one byte could be a more powerful checksum
};
unsigned char calcCheckSum(struct MyMessage msg)
{
//...
}
unsigned int validateCheckSum(struct MyMessage msg)
{
//...
if(valid)
return 1;
else
return 0;
}
Now, you should check every 4 byte (the size of MyMessage) in a sliding window fashion if it is valid or not:
void findMessages( )
{
struct MyMessage* msg;
byte size = Serial.readBytes(input, INPUT_SIZE);
byte msgSize = sizeof(struct MyMessage);
for(int i = 0; i+msgSize <= size; i++)
{
msg = (struct MyMessage*) input[i];
if(validateCheckSum(msg))
{// found a message
processMessage(msg);
}
else
{
//discard this byte, it's a part of a corrupted msg (you are too late to process this one maybe)
}
}
}
If It's not a fixed size, it gets complicated. But i'm guessing you don't need to hear that for this case.
EDIT (2)
I've striked out this edit upon comments.
One last thing, i would use a circular buffer. First add the received bytes into the buffer, then check the bytes in that buffer.
EDIT (3)
I gave thought on comments. I see the point of printable encoded messages. I guess my problem is working in a military company. We don't have printable encoded "fire" arguments here :) There are a lot of messages come and go all the time and decoding/encoding printable encoded messages would be waste of time. Also we use hardwares which usually has very small messages with bitfields. I accept that it could be more easy to examine/understand a printable message.
Hope it helps,
Gokhan.
If faster is really what you want....this is little far fetched.
The fastest way I can think of to meet your needs and provide synchronization is by sending a byte for each color and changing the parity bit in a defined way assuming you can read the parity and bytes value of the character with wrong parity.
You will have to deal with the changing parity and most of the characters will not be human readable, but it's gotta be one of the fastest ways to send three bytes of data.

An Audio Buffer after mpg123_read, what is it? How can I manipulate it?

This is the example code:
while (mpg123_read(mh, buffer, buffer_size, &done) == MPG123_OK)
{
// -> I'm consider this line
if((ao_play(dev, (char*)buffer, done)==0)){
}
}
In this code i want to edit the audio before it's played. Anyone suggest me to use fft to do this, personally i'm try to do this:
while (mpg123_read(mh, buffer, buffer_size, &done) == MPG123_OK)
{
buffer=((int)buffer)*2
if((ao_play(dev, (char*)buffer, done)==0))
}
for experiment, but this can't do anything. So, what is a buffer? How i can change it in real time? And can i stop it and after resume it (also called "pause" in music player..)?
Sorry for noob questions but I'm starting to program just from 6 months.
A buffer is a memory block used to contain an arbitrary, up bounded amount of data. In C, it's used as an array. If the buffer is dynamically allocated, then the variable buffer is a pointer that points to the address where the actual buffer (memory block) begins. You have to look at the declaration of variable buffer to know what is the type of the elements inside such array.
Also you have to look at the mpg123 documentation to know how to interpret the data that is returned by the mpg123_read() function.
Making an educated guess based upon the nature of the data you have decoded, I would say that buffer is probably an array of interleaved short ints that comprises data for stereo channels L and R of an uncompressed 16-bit audio signal. Channel L being at even indexed elements, and channel R being at odd indexed elements.
So, a possible editing would be like this:
for (int i=0;i<done;i+=2)
{
buffer[i] = (buffer[i+1] - buffer[i]) / 2;
}
This would substract left channel data with right channel data, cancelling any audio data that is identical on both channels. It's the basic technique for cancelling vocals in a song.
Your proposed editing has no meaning. You are changing the value of the pointer buffer by multiplying it by two. That makes the pointer to have a very different memory address, much possibly illegal, so when that pointer is used in ao_play() you will get a segmentation fault.
I guess that what you want to do with your example is to make your audio data twice louder, don't you? In that case, you are looking for this:
for (int i=0;i<done;i+=2)
{
if (buffer[i]>16383)
buffer[i] = 32767;
else if (buffer[i]<-16384)
buffer[i] = -32768;
else
buffer[i] = 2*buffer[i];
}
To stop and resume, you have to find a way for your program to check the value of something you can change with an input device (a button pressed in a window, a key pressed, etc).
For example, let's say you have a function called khbit() that returns non zero if a key is being pressed (this function is present in DOS compilers and sometimes is available as non-standard library for easing portability of older DOS programs: look at conio.h if you have it). Then you can do something like this:
int paused = 0; /* flip-flop variable to pause/resume playing */
while (mpg123_read(mh, buffer, buffer_size, &done) == MPG123_OK)
{
if (!paused)
{
if((ao_play(dev, (char*)buffer, done)==0))
break;
}
if (kbhit() && getchar()==' ')
paused = !paused;
}
This will play/pause your music using the SPACE bar.
It will not pause the music, only mute it. Reading (mpg123_read) goes on so you're just skipping a part.

USART transmit problems on a PIC

I'm trying to send data to an SD card from a PIC18f4580, but the PIC is not sending what it should be.
related global variables:
unsigned char TXBuffer[128]; //tx buffer
unsigned char TXCurrentPos = 0x00; //tracks the next byte to be sent
unsigned char TXEndPos = 0x00; //tracks where new data should be put into the array
I am adding data to a buffer using the following function:
void addToBuffer(char data){
TXBuffer[TXEndPos] = data;
TXEndPos++;
}
And putting the data from the TXBuffer into TXREG with the following interrupt:
else if (PIR1bits.TXIF == 1){
if((TXEndPos - TXCurrentPos) > 0){ // if there is data in the buffer
TXREG = TXBuffer[TXCurrentPos]; // send next byte
TXCurrentPos++; // update to the new position
}
Using an oscilloscope I am able to see that the PIC is sending 0x98, regardless of what I put into the buffer. In fact I never put 0x98 into the buffer.
However, if I replace
TXREG = TXBuffer[TXCurrentPos];
with
TXREG = 0x55;
or
TXREG = TXCurrentPos;
then I get the expected results, that is the PIC will send 0x55 repeatedly, or count up from 0 respectively.
So why does the PIC have trouble sending data from the array, but any other time it is fine? I'll emphasize that transferring is handled in an interrupt, because I feel like that's the root of my issue.
EDIT: It is a circular buffer in the sense that TXEndPos and TXCurrentPos return to 0 when they reach 127.
I also disable the transmit interrupt when TXEndPos - TXCurrentPos == 0, and re-enable it when adding data to the buffer. Really, my code works completely as expected in that if I add 13 characters to TXBuffer in main, my PIC will transmit 13 characters and then stop. The problem is that they are always the same (wrong) character - 0x98.
EDIT2: more complete functions are here: http://pastebin.com/MyYz1Qzq
Perhaps TXBuffer doesn't really contain the data you think it does? Maybe you're not calling addToBuffer or calling it at the wrong time or with the wrong parameter?
You can try something like this in your interrupt handler:
TXBuffer[TXCurrentPos] = TXCurrentPos;
TXREG = TXBuffer[TXCurrentPos];
TXCurrentPos++;
Just to prove to yourself you can read and write to TXBuffer and send that to the USART.
Also try:
TXREG = TXEndPos;
To see if this matches your expectation (= the length of your message).
I am assuming there's some other code we're not seeing here that takes care of starting the transmission. Also assuming this is done per message with the position being reset between messages - i.e. this is not supposed to be a circular buffer.
EDIT: Based on looking at the more recently posted code:
Don't you need to kickstart the transmitter by writign the first byte of your buffer to TXREG? What I would normally do is enable the interrupt and write the first byte into the transmit register and a quick look at the datasheet seems to indicate that's what you need to do. Another thing is I still don't see how you ensure a wraparound from 127 to 0?
Also your main() seems to just end abruptly, where does the execution continue once main ends?
There are a lot of things you are not taking care of. TXBuffer needs to be a circular buffer. Once you increment TXEndPos past 127 then you need to wrap it back to 0. Same for TXCurrrentPos. That also affects the test to see if there's something in the buffer, the > 0 test isn't good enough. Generic advice is available here.
Your code is incomplete, but it looks wrong as-is: what happens if there is nothing to send? You don't seem to load TXREG then, so why would anything be transmitted, be it 0x98 or anything else?
The way it is usually done when this kind of code architecture is used is to turn off TXIE if there is nothing to send (in a else part of the IRQ routine), and turn it on unconditionally at the end of the addToBuffer function (since you then know for sure that there is at least one character to send).
Also, you should test TXEndPos and TXCurrentPos for equality directly, since that would let you use a circular buffer very easily by adding two modulo operations.

Resources