First off, this thing I'm doing here is setting up a PID controller in an arduino mega board and the testbench that I'm using is matlab. So, for now I'm at the serial comms, sending data back and forth to see what is going to work best for me. I wrote this code to test:
void setup() {
Serial.begin(9600);
delay(2500);
unsigned long num = 0;
unsigned long temp1 = 0;
char temp2;
int c = 0;
while(1){
while(Serial.available()>0){
temp2 = Serial.read();
temp1 = temp1 | temp2;
temp1 = temp1 << (c* 8 );
num = num | temp1;
temp1 = 0;
c++;
}
if(c!=0){
num = num + 230UL; // << doesn't work
Serial.write(num);
c=0;
num=0;
}
}
}
So, I'm sending a big number (uint32) from matlab to arduino (littleendian), reconstruct the number in a ulong variable and try to do some math with it. Then, send it back to matlab to check. If I don't use the sum instruction, it works fine, number goes and comes back ok. If I sum, this is what i get:
number 100000 sent to arduino >
response is >
4th 3rd 2nd 1st bytes
230 231 108 134 DEC
It doesn't sum 100000+230, it sums 230 to each byte of 100000.
WHY!??!?!!?
I've looked at it for like 3 hours last night and didn't find anything. Idk, it feels like it's a noob question hahaha.
You loop reading data from serial and assume that the whole of the string will be available. That assumption is in correct. You are only getting part of the string.
BulldogLowell, thx!
I don't use loop because it was asking to declare variables inside it, meaning, variables I declared in setup() were not recognized in loop(). So, i just ditched it...
About, serial.print or write, write version works fine, I get the bytes in matlab and reconstruct the numbers just fine.
Holmes, got it! I'll add some delay and see if works.
DeltaG, I wrote this after testing another parse functions that didn't work as expected. I'm just sending a 32bit unsigned number, byte per byte, littleEndian sequence and reconstructing it in a variable.
In the main loop, whenever the board receives something, it goes into the serial.read loop and only leaves the loop after reading 4 bytes from the buffer. In the example, the number I sent was 100000, so "num" equals binary 100000 when the read is done. So, it only goes into the if() if there's a number in "num", then I add anything to it and send it back to matlab. The if() part should run once for each number received.
void setup() {
Serial.begin(9600);
delay(2500);
unsigned long num = 0;
unsigned long temp1 = 0;
byte temp2;
int c = 0;
while(1){
while(Serial.available()>0){
if(c==0)delay(10);
temp2 = Serial.read();
temp1 = temp1 | temp2;
temp1 = temp1 << (c*8);
num = num | temp1;
temp1 = 0;
c++;
}
if(c!=0){
num = num + 230UL;
Serial.print(num);
c=0;
num=0;
}
}
}
Now it works! sending the correct number in bigEndian sequence to matlab. Now I can code the PID :).
Bulldog, you were correct asking about the serial.write(). The way my code was working before gave me the false impression that serial.write was working ok.
I did this just to understand how serial comms works. Now I have to think about creating a simple protocol to control the comms or not. And there is a timming restriction for the controller response so I still need to figure out how to use IRQs, if it is worth it or not.
Ewertsp:
I did this just to understand how serial comms works. Now I have to think about creating a simple protocol to control the comms or not.
I'm sure I sound like an ass when I say this but... if the code you posted in reply #6 was to "understand how serial comms works" I'd have to say you didn't really learn anything useful.
I wouldn't waste any time worrying about interrupts when you've got such large delays for no good reason (and not to mention that your serial code isn't very...uh... robust?). Besides... isn't serial input already interrupt driven?
Food for thought I hope - I'm not trying to beat you up.
Regards,
Brad
KF7FER
PS I don't mean that you shouldn't ever use delay(). Like anything it has it's place when used carefully. But not in a routine where you receive data via serial I/O
It depends on which kind of process (transfer function on matlab) is going to be controlled by the PID. It doesn't matter if I waste 10ms-100ms transfering data, plus 50ms doing math if the time constant of my process is 2s for example.
So far, I know that hardware interrupts are the thing I'd use in a real process. Like this > Arduino Hardware Interrupts Tutorial
For simulation purposes in matlab, I still didn't find anything that works similarly, via usb. So next thing I'm doing is writting the rules of comms based on the PID's features.
Ewertsp:
It depends on which kind of process (transfer function on matlab) is going to be controlled by the PID. It doesn't matter if I waste 10ms-100ms transfering data, plus 50ms doing math if the time constant of my process is 2s for example.
Ok so you can delay plenty in some cases but I thought you wanted to know how serial I/O really worked? The key here is the word "understand". You used that word before, I was just trying to help.
So far, I know that hardware interrupts are the thing I'd use in a real process.
I'm sorry since we were talking serial I/O I assumed you were talking about using interrupts for that. There are many reasons to use them but serial I/O isn't one of them. My bad.
Brad,
My ideia was to use irqs in this simulation to make it more "real" only. With hardware interrupts, I can trigger a read() with the feedback A/D's clock and calculate the next input for the process. So the whole read>math>write will add a small delay between A/D's clock trigger and D/A's output that should be way smaller than what I would see in this simulation, I assume so at least. Even if my process time constant is high I'd always want to make this delay as small as possible so I can use the board to do other things or crank up the sampling rates to improve the control action. Any insights about it?
Nick, that loop is not supposed to exit, ever hehehe
So I finished the controller coding with antiwindup, bumpless parameters transitions and backtracking but I'm still deciding how to proceed on the matlab part... I tried to use simulink's matlab functions blocks with no success. Now I'm looking at another types of custom blocks.