in reply to Re^4: Win32::SerialPort ; close / open problem
in thread Win32::SerialPort ; close / open problem

Ah, that is somewhat what I suspected! Some time later in the year I suspect I may be facing a similar problem, although I'll be tacking it in C++ and possibly with a device driver so I'll have a degree more control over the process.

You'll notice when the device is installed that it actually installs about three separate devices that build a driver stack. Talking to the Serial API that talks to a serial driver that sits on a hardware abstraction layer that sits on a USB driver makes that sort of device a little dodgy! I'll be very interested to hear how you get on.


True laziness is hard work
  • Comment on Re^5: Win32::SerialPort ; close / open problem

Replies are listed 'Best First'.
Re^6: Win32::SerialPort ; close / open problem
by philipMac (Novice) on Jul 26, 2009 at 14:16 UTC
    Yeah, I noticed this sort of shenanigans with the last chip I was working with alright. Quite complicated so it is. In fact I suspect that it wasn't quite working properly, as every now and again it would bork spectacularly and in ways that are very much not like what it says on the tin.
    It wasn't a massive deal, since we were still prototyping, so I let it slide, and crossed my fingers when investor eyes were on me.
    There are many potential points of failure in these setups, not least of which was my dodgy modified Linux driver.
    I will indeed let you know how it shapes up.
    Here, do you mind me asking, (I will make the assumption you too are also coding up for Win32 machines) why are you using C++, and not C# to solve your problem? That was going to be my next port of call for the production code. You appear to have quite a lot of control over whats happening from the brief look I had.

      Under Windows, for various reasons, any kernel mode code must be written in C (not even C++) and we use C++ as our main production language.


      True laziness is hard work
Re^6: Win32::SerialPort ; close / open problem
by philipMac (Novice) on Aug 09, 2009 at 17:15 UTC
    Alright, so I am working my way through the Win32::FTDI::FTD2XX stuff, and I have narrowed it down, again, to a single problem.
    Say I boot the machine, open a port, start reading stuff in, everything is fine. There is no problem.
    Then say I unplug the device, I see this, catch it, and try to re init a new port and it will never work. If I close the program, and restart the program, it will never come back. All the data that comes in unpacks to rubbish.

    Then, this is where its interesting, then I open the port in RealTerm or some Win app, and something is reset. I can then close RealTerm, and restart my program and everything works perfectly... until I unplug the device again.
    So, there is clearly something odd going on. Like I said, even my closing the program, and restarting it cannot get my data coming in sensibly, it is always trash, _until_ I open the port with RealTerm. Once I reset it with RealTerm I can perform whatever operation on the device I feel like, and it always comes back to me, still running.
    Ie, I can
    $FTD->StopInTask; $FTD->Purge; #$FTD->SetResetPort; #$FTD->ResetDevice; $FTD->CyclePort; sleep(9); #get stat, create new $FTD, read data;

    and so on and so forth. I have tried pretty much... (over the last three weeks) every combination and incantation of the various reseting type of commands, I can never get the data coming in properly again until I "reset" something with RealTerm.

    I would really like to know what RealTerm is doing that I am failing on.

    Edit; in fact I was slightly incorrect here. I said if I booted the machine, and plugged in the USB, or let it boot with the USB connect it will _not_ work properly.
    So, it seems that in all cases I must first open the port in say RealTerm, even just loading RealTerm and killing it, even without setting Baud, simply opening the program and closing it resets port, and it will work perfectly. Up until this point, it will appear to work properly, until I actually look at the data coming in, and see that it is rubbish.
    Also, there is also an odd number of bytes coming in until the RealTerm gets loaded. There should be 9 bytes every second or so. Unless realTerm is loaded its ~always some other number, often 10 or 11.
      Ok, so I was thinking about this business with the byte number being wrong.
      I wondered what would happen if I did not set the Baud, and lo, the same behavior occurred. If I set the baud at some high number, it will just give zeros, as expected.
      It should be setting the baud though. I have it set to let me know if there were problems.
      FYI, here is the code.
      use warnings; use strict; use Win32::FTDI::FTD2XX qw(:DEFAULT FT_BAUD_2400 FT_BITS_8 FT_STOP_BITS_1 FT_PARITY_NONE FT_FLOW_RTS_CTS PFT_MODEM_STATUS_CTS ); my $FTD = Win32::FTDI::FTD2XX->new(); unless( $FTD->PFT_STATUS() == FT_OK ) { printf( STDERR "FTD2XX::new() failed: %s (%s)\n", $FTD->PFT_STATUS_MSG(), $FTD->PFT_ERROR() ); exit( 1 ); } printf( "FTD2XX::new() allocated PFT_HANDLE: %d\n", $FTD->PFT_HANDLE +() ); my $numDevices = $FTD->GetNumDevices(); unless( $FTD->PFT_STATUS() == FT_OK ) { printf( STDERR "FTD2XX::GetNumDevices() failed: %s (%s)\n", $FTD->PFT_STATUS_MSG(), $FTD->PFT_ERROR() ); exit( 1 ); } printf( "Found $numDevices FTDI devices connected!\n" ); $FTD->PFT_DEBUG(1); unless ($FTD->OpenByIndex(0)) { print "Problem opening Port 0\n"; return 0; } unless ($FTD->Purge(FT_PURGE_RX)) { print 'cannot purge'; } unless ($FTD->SetBaudRate(FT_BAUD_2400)) { print "Baud is set\n"; return 0; } peek_buf(); sub split_len { my ($len, $string) = @_; $string =~ m/.{1,$len}/g; } sub peek_buf { my ($amountInRxQueue, $amountInTxQueue, $eventStatus) = $FTD->GetS +tatus(); print "trying to read $amountInRxQueue\n"; while ( $amountInRxQueue< 45) { ($amountInRxQueue, $amountInTxQueue, $eventStatus) = $FTD->Get +Status(); print "$amountInRxQueue in q\n"; sleep(1); } my ($bytesReturned, $readBuffer) = $FTD->Read($amountInRxQueue); my $numHex = $bytesReturned*2; my $upack = unpack("H$numHex", $readBuffer); my @a = split_len(18, $upack); print join "\n", @a,"\n"; }
        Solved it. When you init a new FTD, I needed to
        sub init_FTD { my $FT = Win32::FTDI::FTD2XX->new(); unless( $FT->PFT_STATUS() == FT_OK ) { printf( STDERR "FTD2XX::new() failed: %s (%s)\n", $FT->PFT_STATUS_ +MSG(), $FT->PFT_ERROR() ); return 0; } printf( "FTD2XX::new() allocated PFT_HANDLE: %d\n", $FT->PFT_HANDLE( +) ); # $FT->PFT_DEBUG(1); unless ($FT->OpenByIndex(0)) { print "Problem opening Port 0\n"; return 0; } unless ($FT->SetBreakOn) { print "failed to set brake\n"; } unless ($FT->Purge(FT_PURGE_RX)) { print 'cannot purge'; } unless ($FT->SetBaudRate(FT_BAUD_2400)) { print "Baud is set\n"; return 0; } return $FT; }

        otherwise all the data that comes in is seemingly junk.

        That was incredibly painful to figure out. I knew I would get there though, once I asked for other people's assistance. Its the way of things.