PDA

View Full Version : Serial Communication data loss and the best way to send 'parameters' to a BS2?



EEder
02-28-2005, 01:28 PM
My BS2 is running a program which reads input from the Serial line connected to my PC and depending on the input, it does a few different things (turns on/off lights, moves a servo). While a lot of this is already technically working, I'm having a few problems I'm sure you fellas have encountered beofre.

1) I'm noticing that if I load up my PC and send out the TURN_ON_GREEN_LIGHT command, nothing happens. But if I put my PC in a loop sending out that command constantly, it works! I'm getting the feeling the BS2 is missing some of the serial data. Whats going on here? (My BS2 code is below)

(PC sends a ! before the op_code



sync CON "!"

DO
SERIN 16, 84,[WAIT(sync), DEC op_code]

IF (op_code = TURN_ON_GREEN_LIGHT) THEN
HIGH 5 'turns on the light
ENDIF

'... check for other op_codes
LOOP







2) One of the functions that needs to happen is for the BS2 to move two different servos to a position. For this, my PC needs to send
a) The opcode for "Move to"
b) The X coordinate
c) The Y coordinate
d) The rate of movement

My initial thought was:



MOVE_CODE CON 1
sync CON "!"
x_coord VAR Word
y_coord VAR Word
rate VAR Word

SERIN 16, 84,[WAIT(sync), DEC opcode]

if (opcode = MOVE_CODE) THEN
SERIN 16, 84,[WAIT(sync), DEC x_coord]
SERIN 16, 84,[WAIT(sync), DEC y_coord]
SERIN 16, 84,[WAIT(sync), DEC rate]

'...execute the movement on the servos

ENDIF




But this doesn't seem to work, and I presume its because some of the data is being missed over the serial line, like I mentioned in my first problem.

Whats the best way to essentially pass parameters to your BS2?


Thanks ahead of time for the help!

-Brad

Larry
02-28-2005, 02:07 PM
Do you have a pause between writes in the PC code?
The Stamp needs time to go through the loop between each SERIN read. That may be why multiple writes works.

Larry

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

EEder
02-28-2005, 02:58 PM
Larry said...
Do you have a pause between writes in the PC code?
The Stamp needs time to go through the loop between each SERIN read. That may be why multiple writes works.

Larry



How long would you think an appropriate amount of time?

I have paused for up to 10 full seconds after the PC writes the first piece of data onto the serial port. Then upon reading, the PC reads the exact data it just wrote onto the port. It can't possibly take ten seconds for the BS2 to go through a loop of :




MainInputLoop:
DO
SERIN 16, 84,[WAIT(sync), DEC dat]
'A bunch of "IF (dat = doThisParticularCommand) THEN gosub Whatever" statements

ENDIF
LOOP






My PC code looks something like:




aPort.write("!3", 2);
::Sleep(10000);
while (!((z = aPort.read()) == ack))
{
std::cout << "read: " << z << std::endl;
}




It basically write "!3" to the port, sleeps for 10 seconds, then reads whats on the port and prints it out if its not the ACK its looking for and keeps looking.

Is it possible that the PC is somehow holding onto the port and preventing the BS2 from reading from the serial line?

Bruce Bates
02-28-2005, 03:16 PM
Brad -

My suspicion is that the "DEC dat" may not be completing as quickly as you expect it will. Check the manual for what terminates a DEC formatter. In the meantime, try this:

aPort.write("!3 ", 2); <== space added after !3 modified as appropriate
::Sleep(10000);
while (!((z = aPort.read()) == ack))
{
std::cout << "read: " << z << std::endl;
}

That will immediately terminate the DEC formatter, so see how that fares. You may also want to consider using a TIMEOUT parameter in your SERIN statement in a future version to prevent possible hangs. Just as an added thought, at least during testing to know when control is being transferred between the PC and the Stamp, you might want to consider the use of FLOW CONTROL. Later if you get your timing down to a science, it could be removed.

Regards,

Bruce Bates

Larry
02-28-2005, 03:18 PM
It is certainly possible that the operating system is goofing with your serial port.

Do you use XP or a USB dongle?

I beleive there are work-arounds, but since I don't use XP, I never looked into them.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

SPENCE
02-28-2005, 03:53 PM
EEder

MIGHT I SUGGEST, YOU MIGHT CONSIDER HAVING THE STAMP ECHO BACK TO THE PC, THE DATA AFTER IT HAS BEEN RECEIVED.

73
SPENCE
K4KEP

EEder
02-28-2005, 04:07 PM
Bruce Bates said...
Brad -

My suspicion is that the "DEC dat" may not be completing as quickly as you expect it will. Check the manual for what terminates a DEC formatter. In the meantime, try this:

aPort.write("!3 ", 2); <== space added after !3 modified as appropriate
::Sleep(10000);
while (!((z = aPort.read()) == ack))
{
std::cout << "read: " << z << std::endl;
}

That will immediately terminate the DEC formatter, so see how that fares. You may also want to consider using a TIMEOUT parameter in your SERIN statement in a future version to prevent possible hangs. Just as an added thought, at least during testing to know when control is being transferred between the PC and the Stamp, you might want to consider the use of FLOW CONTROL. Later if you get your timing down to a science, it could be removed.

Regards,

Bruce Bates


Thats an interesting suggestion, and I just tried it with no luck. I added the extra space after my opcode to make it "13 " which didn't change anything. Then, I changed the formatter to DEC1 instead of just DEC, which according to the manual should look specifically for a 1 digit decimal number, which is exactly what the 3 is that follows the !. That too didn't work. Executing the above C++ code sends out the command and then waits for 10 seconds, then reads it right back. All the while , the BS2 is sitting there without putting on its lights.

Interestingly enough, look at the following:

If I change my C++ code to:




int iterationNumber;
while(1) {
std::cout << "Sending GreenLightON # = " << ++iterationNumber<< std::endl;

aPort.write("!3 ", 2);
::Sleep(1000);
}




Every time, on the third iteration, the light goes on, regardless of the ::Sleep() time.

Any ideas?



*Note - Yes, I am using Windows XP. Its going straight through a Serial Cable.

EEder
02-28-2005, 04:26 PM
Additionally, the C++ Serial Port class I'm using is ComPort, available from BBSoft: http://www.bbdsoft.com//win32.html

It seemed to be a quick and straightforward method of accessing ports, but seeing as how I've never used it, I shouldn't rule it out as whats causing the problem.

I'm inclined to think this is the case.

I've loaded up HyperTerminal and connected it to COM2. The first time I enter the command, nothing happens. But once I enter it again, it goes out ot the BS2, the command is executed, and the BS2 sends back the ACK character. From this point on, I can test out my BS2 Microprogram and it seems to be working perfectly, which is good news.

The bad part is that the C++ program I have doesn't seem to be working properly. It still sits there and sends out the command, waits the sleep time and then reads its own command off the serial port... unless I put it in a loop and just flood it. Anyone have any suggestions on a good class for accessing the serial port?

Post Edited (EEder) : 2/28/2005 9:59:28 AM GMT

Forrest
02-28-2005, 05:22 PM
Do you have any other program accessing the serial port? FYI Palm Desktop will interfere with reading/writing data over the serial port and it should be removed from your system for reliable operation.

Bruce Bates
02-28-2005, 05:49 PM
Brad -

At this juncture I'd stop using pin port 16 on the Stamp and use some other pin port. Any other pin port can be used for serial communications, as you're not restricted to pin port 16.

There is a ECHO which is occuring, unbeknownst to you, and reflecting the data back to the PC from the characters sent to the Stamp. The ECHO can not be disabled as it occurs at the Stamp hardware level. That ECHO, of the transmitted characters is probably screwing up your ACK detect routine on the C++ side. The echoing is unique to pin port 16. Sorry I didn't notice it earlier.

Regards,

Bruce Bates

PLJack
02-28-2005, 11:18 PM
This is how I do it.

Stamp:

SEROUT 16, 16468, [ReadyCmd] ' Send Ready 'R'.
SERIN 16, 16468, [Cmd] ' Wait for command.



Code:

try
{
// Note: Cycle looking for requests ('R') from stamp. //
while(Terminated == false && ComReady == true)
{
// Note: Thread not event driven, give CPU a break.
Sleep(10);

try
{
char InC;
// Note: Something in the input buffer. //
if(COM->CharReady())
{
InC = COM->GetChar();
// Note: Stamp ready for more commands. //
if(InC == 'R')
PushCmd();
}
}
catch (Exception &E)
{
//
}
}
}
__finally
{
// Note: Free Stack. //
if(COM != NULL)
{
COM->Open = false;
delete COM;
COM = NULL;
}
}




The COM code is in its own thread so the above code looks tougher than it is.
Basically any command I send to the stamp goes into a software FIFO buffer.
When the stamp receives a command it performs the action required then sends
an 'R' back through the com port.
The code waits for an 'R' from the stamp and then sends the next command in the software buffer.
Then waits for a 'R' from the stamp, etc.... until the buffer is empty.

In other words its a manual software flow control.
I found that trying to sync the timing with code is luke warm at best. Even if you
got it to work, on a faster machine the code would start failing again.

Another solution is to use two pins on the stamp and use a hardware flow control and let
the serial hardware do the buffering.

Post Edited (PLJack) : 2/28/2005 4:36:42 PM GMT

Jon Williams
03-01-2005, 02:09 AM
One way to simplify the process is to send a packet of data (three bytes). For some opcodes, you will simply insert dummy data and the BASIC Stamp will not do anything with those bytes. By always sending a fixed packet you simplify the BASIC Stamp end of things when using the programming port, and you simplify your PC application as well; it knows that the first three bytes after a command transmission are echoed from the BS2 and can be discarded.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
Dallas, TX· USA

Pinoy NYC
03-01-2005, 02:46 AM
Hi Jon,

Is there any other pins that has an rs232 driver ?
according to this thread, pin 2 and 3 has a built-in driver, is this true?

http://forums.parallax.com/forums/default.aspx?f=5&m=64976

Jon Williams
03-01-2005, 03:25 AM
The SOUT and SIN pins (the programming/DEBUG port) on the BASIC Stamp (physical pins 1 and 2 on the chip) have a quasi RS-232 driver; the rest are TTL. You can insert a driver pretty easily -- using a MAX232 or similar device would give you full serial comms without the echoes that come from the programming port, and -- if you have pins -- will let you do flow control. This article will help:

http://www.parallax.com/dl/docs/cols/nv/vol3/col/nv89.pdf

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
Dallas, TX· USA