I need to send a string to Arduino from Python using serial communication. The string is like <-4567-> for example, where < and - are delimiters to be used when I'm parsing the data.
However, I checked what it is being sent to Arduino and I obtain only <. I think it's something with the syntax in Python or how i approached the incoming data to be read.
Below are the codes:
Python 1 : this part is where I write to a list testData1 and testData2 the string that I want to send.
const byte buffSize = 10;
char inputBuffer[buffSize];
char tempChars[buffSize];
char messageFromPC[buffSize] = {0};
boolean newDatafromPc = false;
void loop() {
receivedData();
if(newDatafromPc == true){
strcpy(tempChars,inputBuffer);
noInterrupts();
parseData();
interrupts();
newDatafromPc = false;
}
}
void receivedData(){
static boolean readInProgress = false;
static byte bytesRecvd = 0;
char startMarker = '<';
char endMarker = '>';
char x;
while (Serial.available() > 0 && newDatafromPc == false) {
x = Serial.read();
Serial.write(x); // just to verify on python what was sent
if (readInProgress == true) {
if (x != endMarker) {
inputBuffer[bytesRecvd] = x;
bytesRecvd++;
if (bytesRecvd >= buffSize) {
bytesRecvd = buffSize - 1;
}
}
else {
inputBuffer[bytesRecvd] = '\0'; // terminate the string
readInProgress = false;
bytesRecvd = 0;
newDatafromPc = true;
}
}
else if (x == startMarker) {
readInProgress = true;
}
}
}
void parseData() {
// split the data into its parts
char * strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok(tempChars,"-"); // get the first part - the string
strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
strtokIndx = strtok(NULL, "-"); // this continues where the previous call left off
delayPeriod = atoi(strtokIndx); // convert this part to an integer
}
What I want is just the value inside the string. For example, <-4567-> I want 4567.
Could anyone help me?
I do it because it requires a special treatment since it's a 16-bit data and as a volatile variable, I have to ensure this protection. Help me then instead of complaining. Learning is based on erros and I'm not using this forum to waste people time.
I don't understand why noInterrupts() is being used at all since there is no Interrupt Service Routine that might change a value.
The code in the function receivedData() looks very like the code in recvWithStartEndMarkers() in Serial Input Basics. I wonder why the name was changed?
In any case there is no instance of noInterrupts() in my tutorial and it works perfectly well.
I used the examples of Robin2 to establish the communication. I had to switch atoi() to atol() because the variable delayPeriod is a long int.
The problem is remaining: i'm not able to delay my pulse in the amount of time I want and as @gfvalvo said in a thread before, probably the FIFO structure is not a good solution for me. I'm trying to figure out how to do it. Do you have an idea how i could solve this?
Resuming the problem: I have 2 Arduinos connected to 2 separate oscillators. The oscillations which depends on the discharge of a capacitor occur at a rate of 1Hz. What I need to do: after my Arduino capture this discharge(spike on the oscilloscope), I need to generate a pulse of 60us width and this pulse must be delayed by certain amount of time (this value comes from Python). Until 1s delay I am on the first period, but if I choose around 1,5s, we are on the second period and my system must ensure that it can store previous spikes in orde to generate the delayed pulse later.
@Robin2, if I have data coming from Python like <-VALUE->, with 2 delimiters < and -, by using that function recvWithStartEndMarkers(), am I able to extract the value with parseData()?
I also implemented the python code that you provided me here.
You are misunderstanding how strtok() works. The first time you call strtok(), it searches for the first character that is NOT "-" and sets that as the beginning of the string, then searches for the next character that is "-", and sets that as the end of the string, so a single call to strtok() returns a string containing the number deliminated by the hyphens. A simple Serial.println(strtokIndx) to see what the string looked like could have shown you this. Your function should look like this:
void parseData() {
// split the data into its parts
char * strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok(tempChars, "-"); // get the first part - the string
delayPeriod = atoi(strtokIndx); // convert this part to an integer
}
As others have mentioned, get rid of the noInterrupt(), you are not (at least in the code you have shown) using the variable inside an ISR, so not reason to protect it from interrupts.
Thank you @david_2018! Should I use atoi or atol as delayPeriod is a uint_16 variable ?
I still dont get the result I want. Maybe it's something with timers. From what I could study, my setup is correct. Could you help me if you know something about it ?
this is how I send data to Arduino. The value inside the function sendToArduinos is like "14200" for example. But the whole data is sent like <-14200->.
I have no idea why you have a volatile variable but I cannot think of any reason why it should have any bearing on my serial code.
Yes you can parse the data that is received using the function recvWithStartEndMarkers() - have you not looked at the parse example in Serial Input Basics ? Of course you may need to amend the details to match the sort of data you are sending.
You need to post BOTH your Python program and your Arduino program (complete programs, not snippets) - hopefully both of them are very short. Also post a sample of the output from your Arduino program.
If you are actually sending data in the format of <-12345-> then get rid of the second strtok() in the parseData function.
The way it is written now, if you send <-12345-> messsageFromPC will contain 12345, and delayPeriod will be 0, because the 2nd strtok returns a pointer to an empty string.
void parseData() {
// split the data into its parts
char * strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok(tempChars,"-"); // get the first part - the string
strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
strtokIndx = strtok(NULL, "-"); // this continues where the previous call left off
delayPeriod = atoi(strtokIndx); // convert this part to an integer
}