PDA

View Full Version : Serial Port Communication White Paper


rbayer
06-03-2002, 11:04 PM
While I wait for my white paper to be officially added to the white papers section, I'll post it here for your enjoyment. PLEASE send me comments/suggestions. This is still a first draft, so I'm always looking for ways to improve it.

Brandon Martus
06-03-2002, 11:32 PM
Its in the White Papers (http://www.chiefdelphi.com/forums/papers.php?s=) section now.
[attachment removed to save database space] :)

Ian W.
06-04-2002, 04:50 PM
is the white paper written for C instead of C++? cause looking at some of the things in there, they have C++ functions, but by different names, so i wasn't sure what you were using.

DanL
06-04-2002, 06:34 PM
hmm, can you explain the concept of a thread? I haven't really gotten that far in my C++ expierience. Sounds like it's basically an area for Windows to execute commands and can execute them independent of other threads?

Ian W.
06-04-2002, 07:22 PM
from what i can gather, yes, a thread is an executor, of code that is :D. i'm guessing that a thread is the part that runs down the code interpereting the code, and then running it. hence, if you're stuck in an infinite loop, there is no way you can go to something outside of that loop.

i'm still confused about some of the commands, and how they work though...

VanWEric
06-04-2002, 08:21 PM
I have no solid idea what a thread is, but i thought it was like another program running at the same time. IE freecell and winamp are running at the same time. both are in infinite loops (until they quit) but they both work because the processor looks at one program and then the other -- they are independant. I think a multi threaded program has two peices running independantly of eachother, but the look at eachothers stuff, so that a time dependant communication device or sound device is not screwed over by other processes. of course, i am prolly way off here. THis sounds like a job for MEGA ROBOT DUDE!

rbayer
06-04-2002, 08:40 PM
they both work because the processor looks at one program and then the other -- they are independant.

That is exactly correct. Basically, you can think of this as two programs running concurently. One of them deals with all the user interface stuff (mouse clicks, menu selection, displaying text, etc), while the other one ONLY talks to the serial port. This child process, to use the official name, would also deal with getting the data to the user interface. Far and away the easiest way of doing this is through a global variable.

In my Linux dashboard viewer, for example, all data is stored in a global struct called gRoboData. It is of type RoboData, which is basically just a struct with a variable to store each byte in. The regular part of the program then keeps reading this struct over-and-over again and updating the display as needed.

While this may seem like an overly complicated way of doing things, trust me. It is FAR easier than dealing with non-overlapped I/O.

As for whether this is C or C++, the distinction between the two is very fine. Basically, the way I chose to do multithreading is the C way of doing it. Other than that, all the code could be used under either language. I chose C for the multithreading because using the CThread class and MFC often induces more headaches than its worth.

Ian W.
06-04-2002, 09:12 PM
the thing that me and dan are doing doesn't use MFC, mostly cause we don't know that yet ;).

we're planning on developing a console app that runs in an infinite loop, that grabs the bytes from the serial port, then outputs them to various files. from that, a flash program, also running in an infinite loop, picks up these variables from the text file, and outputs them to a nice, pretty GUI. sure, it's super inefficent, but what the hell do i care? also, yes, it's only for my team, and has to be redesigned every year (the flash part at least). i like the way we're doing it though, because it's a creative solution to a problem.

anyways, all that i need is a mini program that grabs the variables, then just writes them all out to various text files. to do this, i really only need one loop. so, would i not need multithreading to do this, right? all that i need is a simple program that will try to open the com port, and if that works, start transmitting. after the transmission ends (program is closed), the com port must be closed, and then that's all that the C++ program has to do.

if i do need mutliple threads, then i guess i would follow the white paper exactly, and then just do a simple other program to write to the text files. i'm not sure exactly how i would do that, but i have all summer.

so, if someone could tell me whether or not i need mutiple threads? thanks.

rbayer
06-04-2002, 09:26 PM
Despite what it may seem like, you still do need multithreading. Without it, there will be no way to quit the serial capture program. Although, if it is a console app, you should still be able to ctrl+C it. It may lead to some minor memory leaks, but no big deal.

Anyway, the way you are describing doing this is fairly simple. In the SerialThread function, where I said to do the data processing, just sort through the twenty-six bytes it reads in, looking for the begining. Once it finds the begining of a packet, start writing out each byte to a file. You can even do this while inside the SerialThread function.

BTW, what compiler will you be using?

Ian W.
06-04-2002, 10:14 PM
i only know VC++, i think version 6.0, cause that's what i use at school, and what i have at home.

so the serial capture thing is always running, and while it's running, i can't execute any other commands in that thread, is what you're saying? i guess that makes sense, although, it makes everything harder :p.

and for memory leaks, i really don't care, cause i'll be running the program on a school computer (yes, we actually have a laptop from the school :D). the only reason i'm never gona run it on mine is that i'm never going to have a OI/RC in my house, a bit too expensive :D, unless someone makes an OI/RC emulator, as i've heard some talk about.

i'm going to be working on this in computer science, cause i have no more work :p. now i can play outsmart the teacher. i wonder if he knows about multithreading... :D

rbayer
06-04-2002, 10:40 PM
i only know VC++, i think version 6.0, cause that's what i use at school, and what i have at home.
Good. VC++ 6 is probably the best compiler out there. Personally, I use professional edition (gotta love academic licensing), but the commands I gave in the white paper should work for all versions.


i can't execute any other commands in that thread
somewhat. Basically, while the ReadFile function is being called, you can't do anything. If the serial cable becomes disconnected, the ReadFile function will never return, so you won't be able to do anything. Under normal operation, it will return immediately after reading the 26 bytes, so you can just put the processing code right there.


and for memory leaks, i really don't care
OK, I guess. just make sure you restart the laptop periodically so you don't end up with a wonderful BSOD.


As for the OI/RC emulator, that was me talking about doing it and yes, I am currently working on it. I'm about halfway through the PBASIC interpreter, and the rest of it is just trivial UI stuff. I've been sidetracked by my automatic program generator (http://FIRSTprograms.tripod.com) though.

Dave Flowerday
06-05-2002, 10:19 AM
Just a note to add to this conversation: if you kill a program with Ctrl-C or similar, you won't really leak any memory. Memory leakage is a problem that can only occur when a program is running. This is because any dynamically allocated memory that the program requests during execution is allocated on the program's heap. When you kill the program, the operating system frees the program's heap space, which includes any dynamically allocated memory that you forgot to free in the program.

I also have to take issue with the statement that "VC++ 6 is probably the best compiler out there" but I won't get into that right now :)

rbayer
06-05-2002, 11:04 AM
Yeah, yeah, I knew that statement would get me in trouble. How about this: it is the best supported windows compiler out there. As soon as gcc gets all the point and click UI stuff that VC++ has, I will switch in a second. For now, I'm sticking with VC.

With the way windows does handles, it is still possible to have resources allocated after a program quits. While traditional new/delete statements will be freed, there are some weird instances where a program won't free all its handles. As an example, watch your free resource % in the performance tab. The more programs you have run, the lower this number gets, even if you quit programs the "nice" way. Basically, Windows sucks at memory management, and we as programmers need to give it all the help it can get.

Dave Flowerday
06-05-2002, 11:49 AM
How about this: it is the best supported windows compiler out there. As soon as gcc gets all the point and click UI stuff that VC++ has, I will switch in a second.
I thought you were talking about the compiler itself being the best compiler, which I have problems with because the Visual C++ compiler has issues with standards compliance. As for the GUI, there are several nice ones that work on top of GCC. GCC itself is just a compiler, just like the command line compiler that's part of VC++. Personally, one of the biggest benefits for me with GCC or other compilers is that I don't have to use the bloated user interface. I greatly prefer the ease of use and flexibility of a good editor (nedit) and Makefiles coupled with a command line, but that's just me.
With the way windows does handles, it is still possible to have resources allocated after a program quits.
If this is true then that sounds like (yet another) Windows bug. (I can't say that I know much about Windows GUI programming; I try to avoid Windows as much as possible.) A true OS would never allow a user process to allocate memory that can never be recovered, no matter how the application is terminated.

rbayer
06-05-2002, 11:59 AM
A true OS would never allow a user process to allocate memory that can never be recovered, no matter how the application is terminated.

A true OS would also have a decent file permission structure, but then again, Windows isn't a real OS... And that's why I use Linux for any real work. As soon as it becomes possible to compile Windows programs in Linux, I'm making the switch entirely. Even now, most of my personal programming stuff is for Linux (gDash (http://FIRSTprograms.tripod.com) , file converters, math homework helpers, etc).

BTW, do you have the names of any good GUI front ends to gcc? I use glade for Gnome/GTK+, but I haven't found the Windows equivalent.

Dave Flowerday
06-05-2002, 12:23 PM
And that's why I use Linux for any real work
Ahh.. that's what I like to hear :) As far as compiling Windows programs in Linux, I've personally never tried it, but have you looked into Wine (http://www.winehq.com)? They have a Windows compatible API that is supposed to allow you to easily compile programs written for Windows under Linux. They also have a runtime loader that is able to execute some Windows programs under Linux directly without recompiling. I have used this part of it, mainly just to see if it works. It is possible to bring up Word and Internet Explorer, so I imagine smaller, simpler programs will probably work even better.
BTW, do you have the names of any good GUI front ends to gcc?
Unfortunately I don't off the top of my head. Like I said, I just use a text editor and command line personally. I know I've seen some out there that looked pretty good, although I don't know if they were available for Windows or not. If there are any for Linux that are open source, it would probably be possible to compile them for Windows using Cygwin. You're probably already aware of it, but I personally find that the best site for finding free software (mostly for Linux, but some Windows stuff too) is Freshmeat (http://www.freshmeat.net).

Ian W.
06-05-2002, 05:38 PM
void SerialThread(PVOID pvoid){
//the actual serial code goes here
}

does the comment in that code mean for all the stuff you say to do before, to be placed in that function? i'm asking, because it's a bit unclear on that part.

Greg McCoy
06-05-2002, 06:36 PM
I think (correct me if I'm wrong) Windows is the most memory inefficient operating system ever. Combined with the terrible memory leaks in Microsoft Office, you enter the land of multiple reboots.

It's unfortunate that the computer power of today allows programmers to use such inefficient, unclean, crash-prone code.

Memory leaks are evil! :D

DanL
06-05-2002, 07:01 PM
Actually, win2k/xp is supposed to be much better than the win9x's/me. Even from first-hand expierience I know this. The compie that I use as my web/ftp/mysql/counter-strike server uses win2k. Left the thing on for more than two, three weeks without a reboot and with moderate usage - it was just fine.

But then again, in February or sometime around then, I remember reading on Slashdot a Microsoft memo where Chairman Bill said something like during the entire month of february (maybe march?), no new code will be developed and all time and resources will be directed to improving flawed code. Something like that is never a good sign :D

rbayer
06-05-2002, 08:24 PM
does the comment in that code mean for all the stuff you say to do before, to be placed in that function? i'm asking, because it's a bit unclear on that part.
Sorry about that. Only the code that does the actual reading from the serial port and the code that processes the data goes in here. Everything else goes wherever you do the rest of your init stuff. Just make sure you call your init routine before _beginthread. Otherwise, Windows will not be happy.
Basically, it should look like:

void SerialThread(PVOID pvoid){
while(true){
ReadFile(...);
//data-processing code
}
}

If you try something and it doesn't work, feel free to email me the code, and I'd be happy to take a look at it.

rbayer
06-05-2002, 08:28 PM
Something like that is never a good sign

It's also not a good thing when a microsoft exec says that parts of the Message Queue are so poorly written that a hacker could easily break into your system if he found out about it. For full details, check out this (http://www.eweek.com/article/0,3658,s%253D701%2526a%253D26875,00.asp) article--especially the third-to-last paragraph.

Ian W.
06-05-2002, 08:29 PM
ok, thanks a bunch. i want the serial communications code working by friday, or at least sunday, because those are the last two days i'll really have a chance to be playing with the robot. so, if i can get the serial communications down, i can do the rest of the code over the summer, without a robot, and then plug it in next september. then, theoretically, if i haven't changed the serial communications part, it all should work. but we all know about theories, and how they come out... *cough*communism*cough* ;)

Ian W.
06-05-2002, 08:32 PM
Originally posted by rbayer


It's also not a good thing when a microsoft exec says that parts of the Message Queue are so poorly written that a hacker could easily break into your system if he found out about it. For full details, check out this (http://www.eweek.com/article/0,3658,s%253D701%2526a%253D26875,00.asp) article--especially the third-to-last paragraph.

lol, that's so great...

wait a second, i'm still using a windows computer... darn. i think i'm going to be using windows, until i can play all of my games on a linux operating system, without using a huge amount of resources. i know this will probably never happen, but i can hope. :D

DanL
06-05-2002, 08:46 PM
Originally posted by rbayer


It's also not a good thing when a microsoft exec says that parts of the Message Queue are so poorly written that a hacker could easily break into your system if he found out about it. For full details, check out this (http://www.eweek.com/article/0,3658,s%253D701%2526a%253D26875,00.asp) article--especially the third-to-last paragraph.

yeah, I remember seeing that story on Slashdot too not too long ago... hehe, the best part about the link that you gave was the advertisment:

rbayer
06-05-2002, 10:58 PM
You know, I didn't even notice that. But that is probably the funniest ad I have ever seen.

Ian W.
06-06-2002, 02:41 PM
ok, i think i made a tiny serial port reading program. now, i need to send each byte out to it's own text file, so would that be taking place within the "Main" thread? i know i can use the fstream library to output to a file (that's the only way i know, so don't yell at me if there's better ways). if that's the case, then should i also make the array and that stuff a variable that's passed in, so it can be passed to other functions? i don't really understand how threads work together, so i'm a bit confused on how the variable can go from the Read function to the main thread.

if someone could explain this to me, preferably tonight, cause i have access to the robot tomorrow, i'd be grateful, cause i want to test out my little program :D. thanks in advance.

Dave Flowerday
06-06-2002, 03:15 PM
now, i need to send each byte out to it's own text file
I'm hoping you mistyped this. If not, you may want to reconsider your design, because if you put each byte into it's own file you'll be creating 1000 files per second, and there's a good chance that your program won't be able to create the files fast enough (creating a new file on a disk is really slow compared to accessing memory or something similar..)
i don't really understand how threads work together, so i'm a bit confused on how the variable can go from the Read function to the main thread
Threading is definitely an advanced concept that can be hard to grasp at first. Having two threads of the same program running at the same time is very similar to having to separate programs running at the same time with one key difference (there's more, but for now this is the one you're concerned with): They share the same memory space. So, if you create an array (or struct, or whatever) before you create your threads, and then you pass that array pointer to any threads which you create, you can access that same location in memory from different threads. So in this case, you could have 1 thread that was reading information off the serial port and storing it into a buffer, and have another thread reading information out of that same buffer and doing something with it.

Unfortunately, if you start using shared memory like this, you have to take into account the situation where 1 thread tries to write to the same location in memory that another thread it trying to read from at the same exact time. This is a big issue with multithreaded programs. I won't go into it in this message, but if you'd like to know more about this just ask and I'll try to think up a way to explain how it all works without writing a novel here...

rbayer
06-06-2002, 03:59 PM
The easiest thing to do would be not to use the thread (even though I told you before that you should). I think I finally understand what you are trying to do, so I'm changing my other mind. Anyways, I wrote the whitepaper thinking that people would be both getting data and displaying it in the same program. As this is two operations, that means two thread (that's WAY oversimplified, but you get the idea). Since you're only doing one thing, and you don't care about memory leaks, just put the
while(true){
ReadFile(...);
//process data
}
stuff immediately after the serial port initialization stuff. Note that this is NOT the way you will want to do it if you ever write a dashboard from scratch using only C/C++.

As much as I hate criticising other people's software design, I don't think writing the variables to a file will work. The problem is, unless you want to do some realy fun overlapped I/O, chances are both programs won't be able to use the file at the same time. For example, if your flash program has the file open for reading, you won't be able to write to it in the data-capturing programming. And vice-versa. Thus, your programs will continuously be tripping over each other and nothing will happen. Dave is right too. Come up with some form of file format that lets you store all 26 bytes in a single text file. Even just a sequential list would do fine. Just make sure that your flash program reads the data back in in the correct order.

Ian W.
06-06-2002, 04:30 PM
well, about the each byte to it's own file, i'm sure it can all be done in one, now that i think about it. i'm not sure though, cause i don't know flash (that's dan's job).

as for the programs tripping over each other, i don't believe that will happen. to make sure flash could read a constantly updated file, i made a short program. an endless loop that counts from 1 - 100, then starts over at 0. it outputs that to a text file. dan then made a small flash movie that just outputed the 'update' in the file, out to the computer screen. flash wasn't quite as fast as C++, but it ran fine (from what i could tell). so, i believe that there shouldn't be a problem.

and i know this is probably the world's most inefficent dashboard program, but i'd like to think of it as a creative solution. neither dan or i know MFCs or windowed apps. something we haven't learned yet. so, we took our knowledge of console apps and flash, put it together, and hope something cool comes out. :D

also, thinking about the thread parts....
if the serial port is open, can i have file input/output open also? i know only one file can be opened at a time, but i'm not sure if the serial port counts as a file input/output stream.

last thing, can anyone think of any way to jump out of the endless loop besides 'ctrl + c'? the only problem with doing it that way is that it kinda might screw up the computer. grr, so many problems when computer science teachers don't teach you anything about putting C++ to work in the real world...

Dave Flowerday
06-06-2002, 04:34 PM
I wonder if the Flash app can use a pipe? I know some applications on Windows use pipes, so it's possible...

For those who don't know, a program works with a pipe similar to the way it works with a file, except there's no file. This would be a perfect application for a pipe. Basically, the program reading the serial port could write the data stream to the pipe, and the Flash program could read the data from the pipe. This is what I think you're trying to do now, except it eliminates the disk from the equation, and solves the file locking issues that rbayer was talking about.

Speaking of that, I know on Unix two programs can have the same file open simultaneously, as long as only 1 is writing to the file. Can this be done on Windows? I've never tried it there.

Dave Flowerday
06-06-2002, 04:41 PM
You know, I just thought of something else. IBM has this cool technology called Sash that I've read about. It basically uses simple languages like JavaScript and HTML to create what they call a "Weblication" which is really a full fledged program. A description from the IBM site: Weblication is the IBM name for a Sash application that uses Web technologies such as HTML, JavaScript, and XML. Sash Weblications also take advantage of operating system functionality (file system, networking, and user interface). Sash Weblications are built using the Sash Weblications Developer Kit (WDK). The WDK makes it easy for you to develop and publish Sash Weblications on the Web
You probably don't want to start fresh on your project but you may want to check it out for future projects. I've personally never tried it but it sounds cool. It has the potential to make it easy to write GUI applications while still allowing you to work with the hardware (serial port, networking, etc.). Check it out at IBM's Sash site (http://sash.alphaworks.ibm.com/).

It's all free, BTW.

DanL
06-06-2002, 04:52 PM
Okay, let me clarify the design of our dashboard program a little bit.

The key element that we want to have is style and visual apeal. Now, since refresh rate isn't that important, we decided to make the display in Flash.

The problem is that Flash only does scripting - not any real programming. It's designed for the web, not real programming. As I see it, the only way to get Flash to read the info from the Dashboard is to use the import data options in Flash.

Flash has two ways to inport data. One is to read from a text file, and the other is to get it in through a server-side script - php, asp, cgi, etc. (remember, flash was designed for the internet, not programming). To get it from a server-side script, I suppose the best way would be to make it read from a database. However, 1. we don't know how to access databases in C/C++. and 2. even if we could, I'd think that having the C++ store the info in a database, then have flash request the info from a php page several times a second is a bit slower than the alternative.

The second way flash imports data is by a text file. We decided the fastest way would be to have the C++ proggie running in the background and constantly rewriting the text file while the flash proggie reads the data and displays it in style.

Yes, we realize this isn't the most efficient way, but again, our priority is style over refresh rate. The goal of this proggie is more of something that shows off to potential sponsors or visitors what we can do - not something for debuging the robot like StangSense (which is something I'd definately like to learn more about some other time).

We did consider that this would be very inefficient. However, to test just how inefficient it was, Ian and I created two small test proggies. The C++ one basically wrote to the text file one variable in an infinite loop, and the flash displayed it. Using just one variable and no additional calculations, the refresh rate is still better than we expected - easily about 10 times per second. I'm not sure how the additional calculations (both decoding the data sent in and the calculations required in the display proggie) will affect speed, but it should be good enough for our purposes.

DanL
06-06-2002, 04:55 PM
Originally posted by Dave Flowerday
I wonder if the Flash app can use a pipe? I know some applications on Windows use pipes, so it's possible...

For those who don't know, a program works with a pipe similar to the way it works with a file, except there's no file. This would be a perfect application for a pipe. Basically, the program reading the serial port could write the data stream to the pipe, and the Flash program could read the data from the pipe. This is what I think you're trying to do now, except it eliminates the disk from the equation, and solves the file locking issues that rbayer was talking about.

Flash I'm pretty sure can't do that - as I explained, Flash just imports either through a text file or through a server-side script. But I'm sure Macromedia has taken this into account. I'm pretty sure other Macromedia things like Director or ColdFusion are designed more for what we're trying to do, but don't hold me to that.

rbayer
06-06-2002, 05:10 PM
last thing, can anyone think of any way to jump out of the endless loop besides 'ctrl + c'? The only way I can think of is to constantly monitor the keyboard and quit if you hit a certain key.

As for having the serial port and file open, it should work. Using regular fstreams, you can have as many files open as you want--no limits as far as I know. Same thing with Windows handles.

Ian W.
06-06-2002, 05:45 PM
ok thanks. only one more problem then. how can i moniter the keyboard without stopping every loop cycle? i know about cin and fin (fstream). that's all. both stop until data is put in and the 'enter' key is hit. that wouldn't do. there must be some way around this, anyone know how? cause if that works, then the program will actually work better than i expected :D

Dave Flowerday
06-06-2002, 05:56 PM
Okay, let me clarify the design of our dashboard program a little bit.

The key element that we want to have is style and visual apeal. Now, since refresh rate isn't that important, we decided to make the display in Flash.

The problem is that Flash only does scripting - not any real programming. It's designed for the web, not real programming. As I see it, the only way to get Flash to read the info from the Dashboard is to use the import data options in Flash.
Yeah I understand your need for a nice looking GUI for this and that's exactly why I suggested Sash. What I understand of it is that it allows you to simply and easily code up fancy GUI programs but also allows you to retain access to serial ports, hardware, etc which Flash does not. Like I said, you wouldn't want to restart your program with this instead by any means, but for future projects it might offer a little more flexibility.

I'm not trying to imply that your design isn't good or won't work. It's actually a pretty common way to pass data around. I was just trying to help think of ways that you can improve the throughput without sacrificing the visual effectiveness of the project. It sounds like you've done the appropriate testing and are confident that this solution will work, so best of luck and keep us posted!

Also, I wrote a program that spits out fake Dashboard port data for use in testing our Palm app for StangSense. Ian mentioned that you are losing access to your robot after this weekend, so maybe this could help. I could probably revive that and you could then hook two PCs together and have one pretend to be the operator interface if that would help... You also might be able to hook a PC up to the Operator Interface and just capture the Dashboard data to a file using Hyperterminal which you could then play back to the other PC. We never got that to work for us (hence the program to generate Dashboard data) but maybe you'd have better luck.

Ian W.
06-06-2002, 06:18 PM
yes, a program like that would be great. i just wish i could take home the extra OI/RC and some joysticks... it's not like i'd break it. heck, i carried a school laptop around at all the competitions. it still works, sorta :D.

Ian W.
06-06-2002, 06:21 PM
also, i'm going to look into that sash thing. seems interesting, so i'll try it over the summer. heck, if i can figure it out, i might just start over. never hurts to do something twice.

SlamminSammy
06-06-2002, 06:23 PM
Originally posted by SuperDanman
Okay, let me clarify the design of our dashboard program a little bit.

The key element that we want to have is style and visual apeal. Now, since refresh rate isn't that important, we decided to make the display in Flash.

The problem is that Flash only does scripting - not any real programming. It's designed for the web, not real programming. As I see it, the only way to get Flash to read the info from the Dashboard is to use the import data options in Flash.

I recommend using C, C++, or PERL to create an ASP program that feeds into a website. Using Adobe Illustrator you can create a very appealing dashboard:)

rbayer
06-06-2002, 08:06 PM
I'll have to check that Sash stuff out too...

Anyway, if you can't get that to work, try the VC++ resource editors. They are simple to use and allow you to create powerful MFC-based programs even if you don't know MFC (sounds impossible, but its true). Also, if you're looking to learn real Windowing/Messaging/GUI stuff this summer, and you want to do it for Windows, I'd recomend you find a copy of Charle's Petzold's Programming Windows. It's a GIANT 1400 page book and is far and away the best one on the Windows API that I have ever read (and it presents it in such a way that you will be able to make the switch to MFC fairly easily later on). Anyway, that was my summer reading last year, and it's what I used to write my RoboGUI (http://FIRSTprograms.tripod.com) program.

Anyway, if you need any real-time help, I'll be on ICQ for the rest of the night while I work on some of my programming projects. #152894206.

Ian W.
06-06-2002, 10:15 PM
i figured out my problem, so no need to show my stupidity :p

Greg McCoy
06-06-2002, 11:20 PM
http://www.theregister.co.uk/media/677.jpg

Dave Flowerday
06-07-2002, 12:07 AM
That's pretty cool! [Except for the defacing other people's property thing...] This one's my favorite:

http://www.attrition.org/gallery/errors/hard-ocp-bsod.jpg

Jay Lundy
06-07-2002, 12:21 AM
Originally posted by rbayer
Also, if you're looking to learn real Windowing/Messaging/GUI stuff this summer, and you want to do it for Windows, I'd recomend you find a copy of Charle's Petzold's Programming Windows. It's a GIANT 1400 page book and is far and away the best one on the Windows API that I have ever read (and it presents it in such a way that you will be able to make the switch to MFC fairly easily later on).
Yes, it's a great book. It's what I've been using to learn Windows programming this summer.

Greg McCoy
06-07-2002, 03:46 PM
Originally posted by Dave Flowerday
That's pretty cool! [Except for the defacing other people's property thing...]

It wasn't me! :D

I got the picture in an email, and I think the billboard was somewhere in England.

Ian W.
06-07-2002, 05:43 PM
grr, i tried my mess of a program out today, and it didn't work. there seems to have been a problem with writing to a file. i' not sure why, but that seems to be where the error was from. there was no syntax errors, so there was something wrong somewhere else. could i actually need two threads? in that case, i think i know what to do, i just need someone to help me on what method i need to take.

rbayer
06-07-2002, 06:31 PM
I'd be happy to help. Just send your source code my way, and I'll help with any parts you need. ICQ: 152894206 (file transfers probably won't work, but just attach them to a message here, and I'll take a look.)

Greg Ross
06-07-2002, 07:37 PM
Originally posted by Ian W.
ok thanks. only one more problem then. how can i moniter the keyboard without stopping every loop cycle? i know about cin and fin (fstream). that's all. both stop until data is put in and the 'enter' key is hit. that wouldn't do. there must be some way around this, anyone know how? cause if that works, then the program will actually work better than i expected :D

I haven't tried this with C++, but in C you use kbhit(). It's possible this might work in C++ too, but it's risky.

Check out in_avail (http://msdn.microsoft.com/library/en-us/vclang98/html/STREAMBU_BASIC_STREAMBUFCCIN_AVAIL.asp). That may do what you want. I believe if you call cin.in_avail() it will return > 0 if a key has been struck. You can simply avoid doing the keyboard read if there's nothing to read.

VanWEric
06-07-2002, 09:53 PM
I wrote 2 apps that talked to eachother (just for fun). One app used kb_event() to put keyboard events out for the other to pick up with getch(). Basically, do keybd_event(VK_(a letter or function),0,0,0); Have the recieving proggie active, use getch and look at the char it returns. IE to send the letter A to the other progg have app 1 go keybd_event(VK_A,0,0,0). The other is waiting with a myrecievingchar = getch(); I wrote a header file to include the letters and numbers (( windows.h has all the kb_event crap, but only defines the keys that arent useful)) I can get that posted if you want it, but it is really just a bunch of #define VK_A 65, #define VK_B...
Oh, and getch is in conio.h

Hope that helped, but i am guessing it didnt.

Mayhaps the unique data sending approach was vaguely interesting though

Ian W.
06-07-2002, 10:02 PM
hmm, i tried the in_avail thing, and it doesn't work. heck, it's not even recognized by my compiler (VC++). as for the rest of my code, i don't use ICQ, so the number you gave me means nothing to me :D. if you want, i do have AIM (yeah, i hate AOL too).

Greg Ross
06-07-2002, 10:31 PM
Originally posted by Ian W.
hmm, i tried the in_avail thing, and it doesn't work. heck, it's not even recognized by my compiler (VC++). as for the rest of my code, i don't use ICQ, so the number you gave me means nothing to me :D. if you want, i do have AIM (yeah, i hate AOL too).
As far as I can tell, in_avail is not non-standard or a new feature. Try calling cin.rdbuf( )->in_avail( ) instead of cin.in_avail( ). I assume you must already be #including <iostream>.

Ian W.
06-07-2002, 10:38 PM
hmm, that syntax works, but how would i run that in a while loop? like, what number does 'cin.rdbuf( )->in_avail( )' equal when no key is pressed? i'm not sure of that.

Ian W.
06-07-2002, 11:14 PM
ok, i've figured out the 'cin.rdbuf( )->in_avail( )' line seems to always equal 0, no matter what i do. how do i change this?

rbayer
06-07-2002, 11:21 PM
after you've done the cin.rdbuf( )->in_avail( ), you must actually read in a byte. a simple 'cin>>myChar' should do nicely. the problem is, in_avail() on checks to see if data is there, it doesn't clear it from the buffer. Therefore, that same data will be there the next time and you will always get 0 back. If you're already doing this, post the offending code and I'll take a look at it.

Ian W.
06-07-2002, 11:33 PM
is there anyway for the computer to skip the cin>>myChar if no data is entered? cause otherwise, the loop will stop once every cycle for me to hit enter. that's no good. could i use the 'keybd_event(i,0,0,0);' event to hit enter, if no data is entered? my whole problem hinges around the fact that i know no way of skipping a cin without putting in data. any help?

rbayer
06-08-2002, 12:13 AM
Going back to a previous post (by gwross), your best method will be to use kbdhit(). It will return 0 if no key has been pressed, and 1 if a key has been pressed. Since I assume you only want it to quit when a certain key is pressed, you can then issue a getch() which will return the key that was pressed. Just compare it, and you should be good to go. Just make sure to include <conio.h>.
Here's the code I tested it with:
while(true){
if(kbdhit()){
cout<<"key pressed:";
myChar=getch();
cout<<myChar<<"\n";
if(myChar=='q')
return 0;
}
else{
cout<<"no key pressed\n";
}
cout.sync_with_stdio()
}

BTW, that cout.sync_with_stdio() is because I was having problems with the output being very sluggish.

Dave Flowerday
06-08-2002, 05:46 PM
It wasn't me! I got the picture in an email, and I think the billboard was somewhere in England
I wasn't trying to imply that it was you by any means...

Greg Ross
06-10-2002, 01:19 AM
Originally posted by Ian W.
ok, i've figured out the 'cin.rdbuf( )->in_avail( )' line seems to always equal 0, no matter what i do. how do i change this?
cin.rdbuf( )->in_avail( ) should return non zero (greater than zero) if there is data in the keyboard buffer. Is this not the case? When you say "no matter what i do" does that include pressing keyboard keys (other than Ctrl-C which is probably handled differently than other keys)? (I know that may sound insulting. That's not my intention. I have worked on a help line, and I've learned to not take anything for granted.) If you are able to read data from the keyboard using cin, then in_avail() should also work.

BTW, for readability (probably not efficiency) you could save the return value of cin.rdbuf() in a variable (say cinBuffer) -- outside the loop and then only call cinBuffer->in_avail() inside the loop.

rbayer
06-10-2002, 01:33 AM
I've been playing around with this too, and I've run into the same problems. It seems that the only way to get data to cin so that in_avail() will notify you is to do a cin! For example, if you call cin<<x, but at the prompt type something like "5 10 15", then in_avail() will return the number of chars that are still in the buffer. In this case, either 6 or 7 (I can't remember which), because the first one has been eaten by your cin statement. As far as I can tell, this would be useful in figuring out how much data a user input, but only after the user actually input the data.

Or I could be completely wrong... Anyway, the code I posted above seems to work (based on your earlier suggestion). If anyone can get this working with cin, I'd be interested to hear how.

Ian W.
06-10-2002, 05:51 PM
well, i tried the _getch () and _getche () functions (from conio.h). just a simple loop to test it, and it worked pefectly, doing exactly what i wanted. from what i understand, it reads the I/O stream, and you don't even have to hit enter. it will just go on and on until there is input on the keyboard, i think. if that's the case, i just need to identify a certain key, and all should work as i want.

Ian W.
06-10-2002, 07:16 PM
bah, that doesn't work, but i have one idea. is there a way that i can say that if getch () is 0, then virtually press the enter key? i know you can do the keyboard part, not sure how though. but if i had it constantly 'press' enter, unless i hit a button, in which case it stops. i think that would work, not sure though.

rbayer
06-10-2002, 07:41 PM
What's not working? Have you tried the code I posted earlier? Make sure to check kbdhit() before you call getch(). That seems to work on my computer.

Ian W.
06-10-2002, 08:08 PM
yeah, i'm going to go and smack myself. i forgot kbhit (), so it kinda doesn't work :p. i feel so stupid now... :D

oh well, at least i know what i'm doing now.

Ian W.
06-12-2002, 09:54 PM
ok, i have my serial communications program working, or at least i think so. there's one part i'm not sure of, which is as follows...

if(!ReadFile(hSerial, szBuff, 26, &dwBytesRead, NULL)) {
//error reading serial port. Process appropriately.
cout << "Uh oh" << endl;
}

the little 'uh oh' was just a phrase i spat out to test where the program was failing. it seems to be able to get up to this statement, and then it freezes. i'm assuming this is because i don't have the robot hooked up to it, but i just want to be sure. i'm going to be testing it tomorrow, i think, so i can be sure about whether or not it works, but i just want to make sure that this line of code (or lines) will work correctly, which it should. if this code works, i think i have the basic program all done, and all i need to do is 'customize' the dashboard, so i can change the numbers to reflect this year's robot program. but i want to make sure the actual basic program works first.

Ian W.
06-12-2002, 10:04 PM
most interesting, as i was trying out the different COM ports (when you initially open the port, the "COM#" line), and when i did COM3, it worked as it should. i'm assuming that means that my computer is set to COM3 and COM4, but i have no idea how that works. so, it appears that my program is working as it's supposed to after all...

one thing though. does a COM port without a incoming signal transmit '-52' out, cause that seems to be what i'm reading... :/

rbayer
06-12-2002, 11:39 PM
In theory, you shouldn't read anything without a device connected; the ReadFile should hang the thread. The easiest way to figure out what COM ports you have is to open up your device manager and look under the Ports category.

Matt Leese
06-13-2002, 09:14 AM
It seems very strange that your computer is setup to use COM3 and 4. I've never seen that. Normally a computer is setup so that the serial port is COM1 and the modem as COM2 (or vice-versa; modems have hardware, called a UART, so that they are treated exactly the same as a serial port). I would suspect that for whatever reason windows is actually letting you open COM3 even though it's not really connected to anything (the open command should fail at that point). I'd also check to make sure that your modem isn't on COM3 (as you should be able to open that). Just as an fyi, 51 is 0x33 and -51 would then be 0xCD which isn't any sort of code that I know. Anyone know any different?

Matt

Ian W.
06-13-2002, 02:34 PM
ok, i figured it out. sorry for the confusion, but i was rather confused last night too :p.

anyways, i realized after that the reason it worked when i opened it on COM3 or 4, was that everything just failed, and because my program is bare basics, it would still continue (yeah, i have to fix that part :p). anyways, it would just jump into the loop, and get stuck. of course, i didn't realize it, but now it all makes sense. so, that problem is fixed.

the other part, about it not working on 1 and 2, is exactly what rbayer said. the read file thread hung up the program, cause there was nothing hooked up (this was at home). today in school, i tried to run the program, but realized i had completely screwed up the array that collected the data, because i'm stupid :D. so, i fixed that, and waiting till tomorrow to test it.

also, in a stroke of luck, i'm taking the robot home for the summer, so i can keep working on it :). looks like i'm not going to die if rbayer doesn't get that PBASIC emulator thing out right away :D. keep working on it though, cause it's a really good idea, especially for at competition, when you usually want to test the code before you use it.

rbayer
06-13-2002, 02:50 PM
Originally posted by Ian W.
looks like i'm not going to die if rbayer doesn't get that PBASIC emulator thing out right away :D. keep working on it though, cause it's a really good idea, especially for at competition, when you usually want to test the code before you use it.

Have no fear! School is out and I have nothing better to do for the next month. It will be done, I just don't know when.

Ian W.
06-13-2002, 03:00 PM
heh, one more day of classes for me...then a week of regents :(. but, i'll have plenty of time after to make some good flash/c++ program, and to fix up the robot. can't wait...

Ian W.
06-13-2002, 04:48 PM
hmm, quick question...

when i had my buggy C++ dashboard port reader running today, i had accedentally set it only to fout (file out) the first byte (yes, very stupid mistake on my part :p). anyways, in Dan's little 'byteviewer' flash program, it came up as various numbers, like 80, 40, -52, etc. i was under the impression that the first two bytes were 0xff, or 255. what's the deal with this?

rbayer
06-13-2002, 05:43 PM
The problem is, there is nothing to guarantee that you will start reading at the beginning of a packet. That is why you have to read in 26 bytes, find the beginning, and then start processing from there.

Ian W.
06-13-2002, 06:40 PM
ah, ok that makes sense. so, i do a first read, finding the double 255/0xff, and then once i find that, start the main loop? i think i know how that should work, although not completely sure.

DanL
06-13-2002, 08:23 PM
Okay, so this part sure is the painful part... after about an hour discussing it, Ian and I decided to do something, just we wanna know if this is the 'correct' way of doing it...

Basically we're going to read in one byte at a time to a fixed queue of 28 positions. When the first two items and last two items are equal to 255, then we know that we have a full packet, and we read the queue for the appropriate information. If all four items aren't equal to 255, then we know we don't have a full packet, and we just continue adding to the queue.

For a visualization (they're easier to understand), I made a simple visualized version of what we're going to do... http://24.186.144.31:81/queue-visual/moo.html

I believe this is going to work, but if it doesn't, how are you supposed to parse the bytes, or, determine where a packet begins?

rbayer
06-13-2002, 08:24 PM
I'd avoid reading one byte at a time if possible. It is inefficient and means your program will loop more often. And if you miss a byte, the output could appear sluggish or delayed. If you want to do something similar to this, I'd recommend that that you just discard data until you find a 255,255 and then copy the next 24 bytes into your data structure.

Originally posted by Ian W.
ah, ok that makes sense. so, i do a first read, finding the double 255/0xff, and then once i find that, start the main loop? i think i know how that should work, although not completely sure.

Everytime through the loop you should resort the data. Otherwise, if you miss even a single bit, the whole packet will be off and the data won't make any sense. My advice is to read the data into a temporary storage space and then sort it into a final one. That's the way I did it in my dashboard program, and it works fairly well. If you want to take a look, the source is at http://FIRSTprograms.tripod.com under the name gDash. Or, I can send you just the relevant portion of code if you would prefer.

DanL
06-13-2002, 08:36 PM
Originally posted by rbayer
I'd avoid reading one byte at a time if possible. It is inefficient and means your program will loop more often. And if you miss a byte, the output could appear sluggish or delayed. If you want to do something similar to this, I'd recommend that that you just discard data until you find a 255,255 and then copy the next 24 bytes into your data structure.

Hmm, well what happens if you loose one of those 24 bytes... it'll be that your 24th byte will actually be the first byte of the new packet... how does your way protect against this?

rbayer
06-13-2002, 08:43 PM
Originally posted by SuperDanman


Hmm, well what happens if you loose one of those 24 bytes... it'll be that your 24th byte will actually be the first byte of the new packet... how does your way protect against this?

You won't. PC serial ports use buffers to store data in. Once you begin the read, you will get 26 continuous bytes. On the other hand, if the buffers overflow between read operations, you might loose a byte or two. Even if you do, by some mysterious fluke of Windows, loose a byte from the middle of a 24-byte read, checking for the start of the packet on each loop will make sure it corrects itself.

DanL
06-13-2002, 08:48 PM
Hmm, well thats a bit more simple than I thought... however, I was more concerned about no information coming over because of a radio failure between the robot and the oi or some interfereance...

Originally posted by rbayer

Even if you do, by some mysterious fluke of Windows, loose a byte from the middle of a 24-byte read, checking for the start of the packet on each loop will make sure it corrects itself.

Well, suppose the check fails... what if the first two bytes aren't 255's... I suppose you have to switch to a read-1-byte-at-a-time loop until you DO get two consequetive 255's?

Ian W.
06-13-2002, 09:03 PM
actually dan, before you even posted that, or at least before i read that last post, that's what i just did. hopefully it will work...

rbayer
06-13-2002, 09:07 PM
I'd think so...

If not, here's the code I used. It takes the cross between two consecutive packets, but it really doesn't matter since the refresh rate is much higher than the eye could ever detect.

int i;
int start;
unsigned char info[26];
for(int i=0; i <=24; i++){
if(readBuff[i]==255 && readBuff[i+1]==255){ //packets start with 255,255
start=i;
break;
}
}

for(int i=start; i<=25; i++){
info[i-start]=readBuff[i];
}
for(int i=0; i<start; i++){
info[i+(26-start)]=readBuff[i];
}

DanL
06-13-2002, 09:41 PM
ahhhh, now I see what you were talking about all along!

Just I don't like the fact that you overlap 2 packets into one... yeah it's too high to pick up, but just so I know I have an understanding of packets, this code would make it get the full packet, right?

int i;
int start;
unsigned char info[26];
for(int i=0; i <=24; i++){
if(readBuff[i]==255 && readBuff[i+1]==255){ //packets start with 255,255
start=i;
break;
}
}

for(int i=start; i<=25; i++){
info[i-start]=readBuff[i];
}

unsigned char remainingBuffer[start];
ReadFile (hSerial, remainingBuffer, start, &read, 0);
for (int j=0; j<start; j++) {
info[26-start+j]=remainingBuffer[j];
}

rbayer
06-13-2002, 09:58 PM
Looks good. It should also align the data for all subsequent reads, making it a little bit faster. Just make sure start isn't equal to 0 before you go into that last block of code, as I don't know how VC++ deals with arrays of size 0 or how ReadFile deals with requests of length 0. Might be OK, might cause page faults; you never know 'til you try.

I definately agree that overlapping two packets isn't ideal, but I was too lazy to change it after I realized that was what it was doing (I wrote the algorithim around 3am last year in Florida and wasn't quite thinking right).

Matt Leese
06-14-2002, 09:00 AM
When I wrote my dashboard viewer, I took a bit different take on how to read in the data. I did read in everything one byte at a time. Once I received two 255's, I then started a count. Given the value of the count, I determined what data I was actually reading in. Given that, I processed the data into a structure (ie the structure was updated everytime through the loop which means everytime a byte was read). Then, once the count reached the end of data, I updated the display.

As far as speed issues go, there is no problem reading in a byte at a time. Remember, the data will only be coming at you 20 times per second (20 Hz) which is something a computer can easily process.

Matt

Ian W.
06-14-2002, 02:37 PM
one quick problem/question...

is it in anyway possible to loose a byte or two between reads? i'm doubting that, because of what i've heard, but it's something that's probably useful to know :p.

rbayer
06-14-2002, 02:58 PM
theoretically, yes. Probably, no. The only way you could loose a byte is if the PC's buffers overflow, and the only way I can imagine this happening is if you do a lot of time-consuming work between reads.

DanL
06-14-2002, 03:09 PM
What about if there's a break or interfereance in the radios between the robot and the oi?

Matt Leese
06-14-2002, 03:43 PM
The OI should continue sending data even if there's a break between radios. It will only stall in between packets (ie all 26 bytes); that's because it doesn't have all the data to send.

Matt

Ian W.
06-14-2002, 04:10 PM
so, theoretically, the OI will only send a complete packet, so the only way to get a partial packet is to unhook the cable from the dashboard port? that seems to make the most sense to me, so i'll go with that. also, that would mean we don't need to elaborate on some huge thing to crack down on missing packets and ignore them so they don't screw up the computer. makes everything a bit easier :D.