Serial Communication
flo
Posts: 38
Hi guys,
I've been working on this little project to send serial commands from my computer to the prop. I managed to get it to receive strings which I then convert to decimals and then do some processing on those decimals. However, I realized I was being stupid and I should just send decimals to begin with. This is what I'm sending as a string:
1002255
where the first digit (1) is a command, the next 3 (002) is a channel, and last three (255) is a value. This works fine but I'm sending 7 data bytes when I could send just 3!
I'm very new to serial communication and micro controller programming so I need some help figuring some stuff out.
I'm using FTDI drivers on my computer to send serial commands to the prop. Whats the max baud rate I can use? I need to send 1200 channel-value pairs a second. Is this possible?
I've been working on this little project to send serial commands from my computer to the prop. I managed to get it to receive strings which I then convert to decimals and then do some processing on those decimals. However, I realized I was being stupid and I should just send decimals to begin with. This is what I'm sending as a string:
1002255
where the first digit (1) is a command, the next 3 (002) is a channel, and last three (255) is a value. This works fine but I'm sending 7 data bytes when I could send just 3!
I'm very new to serial communication and micro controller programming so I need some help figuring some stuff out.
I'm using FTDI drivers on my computer to send serial commands to the prop. Whats the max baud rate I can use? I need to send 1200 channel-value pairs a second. Is this possible?
Comments
1200 rate per second x (3 bytes per channel + 1 byte for start/stop-bit and some spare time) = 4800 bytes per second = 38400kbit per second.
You can go up to the megabit per second area with the FTDI.
Here's the code in question (I've also attached an archive to this):
I keep receiving "255 (something)" on my computer. Is the -1 decimal being converted to 255 in ascii?
I'm so confused,
Flo
You might want to change the actual Comm object to send something different then a -1... Just an idea?
PUB rxHexTime(ms) :Value | place, ptr, x, temp
{{
Accepts and returns serial hexadecimal values, such as "A2F4" as a number. <<<<< In this case it is expecting an ascii string "A2F4<cr>"
with a timeout value. No data returns -1
String must end in a carriage return (ASCII 13) <<<<<<<<
x := Serial.rxHexTime(100) ' accept string of digits for value with 100mS timeout
}}
In other words I don't think this is doing what you intend. In fact it is doing the opposite - receiving 4 bytes to convert to 2 bytes.
Also thanks kwinn for pointing that out. So instead of using those wrapper functions (rxDec and rxHex), I'm simply using rxTime to send 4 bytes total.
So I'm sending data packets of 4 bytes: channel, value, $00, and command (The order lets me quickly check if the data packet is done because channel can never be $00).
If I send 4 data packets (16 bytes) it works great. But if I send 8 data packets (32 bytes) it does crazy stuff:
I send the hex equivalent of this (channel:value; bolded to emphasize correlation)
but my prop only sees and echos:
So I'm thinking the buffer is overflowing but if I increase the buffer size to rx_buffer[noparse][[/noparse]64] in FullDuplexSerial, it seems to crash. So is it really the buffer?
If instead I send:
It'll respond:
I've attached the code if it helps any. I'm totally stumped.
Thanks again guys
In your main you don't need to initialize all the button-variables. All variables in the VAR section are initialized with 0 by the compiler. So, each additional initialization is a waste of HUB-RAM.
Please note ... this is not a general advice. Of course there are programs/functions which need to be 'restartable'. In other words the same code is run several times and needs to do it's job from the beginning. There initialization makes sense.
2.
Why do you store bytes in a long array (x)? Once you found out that recByte is not -1 (for timeout), you can store recByte in a byte array.
3.
Hard to say what's wrong, if you only see one side of the code. Maybe the problem is in the sender. Try·to use·debugging-code. For example you can print the complete x-array after receiving a byte to see what it looks like after processing the byte.
·
This version is not designed to have a variable TX/RX buffer-size. It contains a lot of hardcodes which rely on the size being 16. If you change the buffer-size, you have to change some code too. For example the PASM code will not use the additional buffer. The PASM still uses @rx_buffer + 16 for its tx_buffer. That's why it looks like being crashed. SPIN code is writing to tx_buffer, but PASM expects the bytes in @rx_buffer + 16
...
I think there is a version out which has bigger buffers. PhiPi? Cluso? heater? I don't remember ... I'm to old ... ;o)
But a bigger buffer will not fix the problem if your sender can continuously send. Then it will only delay the problems. So, you have to make your loop faster. The button stuff can be done in an additional COG, so it does not eat up your time in the main-loop.
PS: saying that .. to output the whole x-array is of course no longer a good advice ;o)
Post Edited (MagIO2) : 3/9/2010 9:25:14 AM GMT
What's encouraging is that the bug is consistent; the values that get processed are always the same.
At 80 MHz, the prop should be much faster than the 9600 baud that the bytes are coming in at. Why is this being such a problem? Could it be a memory management issue where the other cog isn't able to read while the bytes are coming in? I must be crazy
Beside that it is compatible to FulDuplexSerial.
Andy
I already told you what the problem is - the loop is to slow. In more detail:
The problem is your output-stream. You receive 4 bytes and start to send back 5-7 bytes. And you convert before sending (STR.combine & Num.ToStr) and I did not have a look into DMXout yet, but this at least eats up some time for calling . As you don't sync incoming stream with outgoing stream, the driver receives data while sending and can't process the data fast enough. So, you end up with buffer overflows. Is the program that sends the data written by yourself? Can you change it in the final version? Then you could use a handshake protocol.
If you need to send with this data-rate, you have to split up the program and let several COGs do the job.
I fully commented out the code that reply's to the computer ("str.combine & Num.ToStr") and am left with:
The above code isn't able to send more than 32bytes before it crashes. What I'm trying to get at is that the code you helped me write is better than before (16 vs 32 bytes) but it doesn't explain why it's an input/output stream problem. DMX runs at 250k baud while the prop is receiving bytes at 9600 baud and all the code is doing is receiving bytes and sending to the DMX cog.
Does that mean the slowdown is happening at the memory management level where the HUB's round robin is too inefficient (even if it's running at 40 Mhz)?
You really load the changed program to the propeller or is an old version the top-object?
The baud-rate matches on propeller and PC side?
Propeller is really running with a crystal?
Now I'd first check that the data received is really what you send. Just have a 1kB buffer and fill up it in a quick loop doing nothing else. Then send it back (converted to HEX). Verify the result.
BTW: Are you sure that the channel can't be 0? DMX simply uses channel to put the value into an array. And an array starts with index 0.
Maybe additional 0s cause the problem.