K8055 - delayed delivery of input values

I have had a K8055 board for several years, so it might be an old revision - P8055-1 (2003). I have dusted it off and it seems to be working well using the latest DLL. However, I have a small problem.

I connect output8 to input 5 using a simple wire - this is OK, the open collector output drags down the 10K+10K pull up on the input. Seems to work fine in the GUI - set the output and input sets, clear the output and the input clears. The following code which basically toggles the output as soon as the input changes:

C.ClearDigitalChannel(8); int set = 0; for (int i = 0; i <100; i++) { int bit = C.ReadDigitalChannel(5); fprintf(stdout, "Bit=%08lx\n", bit); if (bit == set) { if (set) { C.ClearDigitalChannel(8); set = 0; } else { C.SetDigitalChannel(8); set = 1; } fprintf(stdout, "Switch=%i\n", set); } }

Yields the following output:

Initialized
Bit=00000000
Switch=1
Bit=00000000
Bit=00000000
Bit=00000000
Bit=00000000
Bit=00000001
Switch=0
Bit=00000001
Bit=00000000
Switch=1
Bit=00000000
Bit=00000001
Switch=0
Bit=00000001
Bit=00000000

This shows that the output takes 2-5 polls to update the input. Given that each poll takes 10ms, the ULN2803 switches in 1us and the PIC is running at 6-24Mhz this should not be. The input should change after the output is changed well before the poll can be received.

The variable delay makes it difficult to test inputs after an output change as one does not know how long it takes to propagate.

Any suggestions ?

thanks

gordon

It seems that at the beginning there is some latency.
I slightly modified the test program to check the delay.
I connected three wires between the outputs and inputs.
The code I run in Borland C++Builder was:

int reads; int writes = 1; Memo1->Lines->Clear(); WriteAllDigital(writes); for (int i = 0; i <100; i++) { reads = ReadAllDigital(); Memo1->Lines->Add(IntToStr(i)+" Read = "+IntToStr(reads)); if (reads == writes) { writes++; if (writes == 8) writes = 1; WriteAllDigital(writes); Memo1->Lines->Add("Write = "+IntToStr(writes)); } }
Here some results.
The loop counter value is printed here too:
[size=85]
86 Read = 7
Write = 1
87 Read = 7
88 Read = 1
Write = 2
89 Read = 1
90 Read = 2
Write = 3
91 Read = 2
92 Read = 3
Write = 4
93 Read = 3
94 Read = 4
Write = 5
95 Read = 4
96 Read = 5
Write = 6
97 Read = 5
98 Read = 6
Write = 7
99 Read = 6[/size]

After every write the old value is read once.
The next read gets the value written to the digital outputs.

This seems to be same result as you got.
At the beginning there is some more delay.

Thank you for your very prompt look at this.

I modified my code to add the following after the “set”:

        int sleep = rand()  * 100 / RAND_MAX;
        fprintf(stdout, "Switch=%02lx sleep=%i\n", set, sleep);
        Sleep(sleep);

I could not modify yours as I did not have the other methods that it relies on. You will also need srand((unsigned)time(0)); somewhere at the start. This is all VC++.

When we run the modified program we find that it takes a random number of samples for the change to propagate - random with respect to the sleep time which is really wierd. So if my program was interrupted -and hence wait’d - once again there would be no way to know how many samples to take.

However, this gave me an idea. I also hooked up a second wire between 7&4 and set/clear the bits in the same order 8 then 7. I can see that the order of delivery is the same. So I sample up until the 7 bit changes and then I know that the 8 bit will be correct.

I really should not need to do this. You have access to the firmware, can you give any rationale for this peculiar behaviour ? I would be struggling if I tried to code for this effect. It is as if the firmware is creating a queue of samples. However, if the firmware was adding a state-entry to the queue based on changes then the number of samples would be independent of the sleep time, if it was adding an entry each time a request was made then the number of samples would be independent of the sleep time, if it was adding an entry periodically then the number of samples would be dependent on the sleep time. Not what we see.

regards

gordon

[quote]However, this gave me an idea. I also hooked up a second wire between 7&4 and set/clear the bits in the same order 8 then 7. I can see that the order of delivery is the same. So I sample up until the 7 bit changes and then I know that the 8 bit will be correct.[/quote]This is good idea to be sure the digital input value is “fresh” one.

[quote]I really should not need to do this. You have access to the firmware, can you give any rationale for this peculiar behaviour ? I would be struggling if I tried to code for this effect. It is as if the firmware is creating a queue of samples.[/quote]There is no queue of samples in the firmware. All the requests from the USB bus are handled immediately. It seems that this strange behaviour is based on the USB system of the PC.

Little puzzled how the USB system can affect the status & reading of an IO pin on the PIC.

However, by the time that I added the additional control statements, the additional polling and a long delay at the start to obtain initial synchronization I am now way outside my performance requirements. It was always going to be tight with a 10ms request/response. I will move on to a different solution.

thank you for looking.

regards

gordon

Strange indeed.
I made similar test with the K8061 card.
It works as assumed.
Here the results:

Read = 1
Write = 2
Read = 2
Write = 3
Read = 3
Write = 4
Read = 4
Write = 5
Read = 5
etc.

Each read/write cycle is about 6.5ms.

int reads; int writes = 1; Memo1->Lines->Clear(); OutputAllDigital(CardAddr, writes); for (int i = 0; i <100; i++) { reads = ReadAllDigital(CardAddr); Memo1->Lines->Add(IntToStr(i)+" Read = "+IntToStr(255-reads)); if (255-reads == writes) { writes++; if (writes == 8) writes = 1; OutputAllDigital(CardAddr, writes); Memo1->Lines->Add(" Write = "+IntToStr(writes)); } }

Are you opening and closing the connection to the card every time gordonb?

The first little app. i made connected to the car, send a command, and then closed right away. That gave me same result as you are getting here, but by opening it, and then sending all commands without closing it again, fixed it for me.

No, single OpenDevice.

    int rc = C.init();
    if (rc == -1)
    {
        fprintf(stdout, "Failed(1) %i\n", rc);
        exit(0);
    }

    rc = C.OpenDevice(0);
    if (rc == -1)
    {
        fprintf(stdout, "Failed(2)\n");
        exit(0);
    }

… then the Sets/Clears. The only pecularity is that it often did not get to the CloseDevice so relied on Windows to close the HANDLES.

I am prodding the problem from a different perspective using code reversed out of the LINUX re-engineer of the DLL fitted into some Jan Axelson code. I am not getting consistent results - I seem to read replies when no request was sent - with synchronous IO, and some times do not get replies to requests; but this could all easily be an artifact of my new code.

I will post if I get anywhere.

I might ultimately endup replacing your PIC on the board with a PIC18F2550.

regards

gordon

You were correct it is an interaction between the protocol supported by the chip and the Microsoft HID driver.

Once I had found the bug that Jan had left in her example code to trap those not paying attention - missing call to GetOverlappedResult() :slight_smile: - I got consistent results and then read the appropriate line in the manual.

The K8055 identifies itself as a HID compatible device and hence Windows assigns the Microsoft HID driver to the address. THe K8055 also says that it will accept Interrupt IN requests and Control OUT requests - I think that it is obliged to do so.

I an using a WriteFile() call to send the 8(9) byte packet to the 8055 to set values and a ReadFile() call to retrieve the 8(9) byte packet from the 8055 containing the current state. The WriteFile() uses a Control OUT request. The ReadFile call retrieves the result of an Interrupt IN request - note the use of English.

From the manual:

The HID driver makes a new request automatically about every 8ms, but it will depend (slightly) on other UBS traffic. This does not quite explain the behaviour that I see but it is close enough - I am sure any other differneces are just getting the test program timing correct.

I tried using the HidD_GetInputReport() API to execute a (synchronous) Control IN request - but this yields a CRC check - I suspect a bug in the PIC code.

So I am back to where I was. It is very difficult to synchronize the IN request with the OUT request. The additional polling pushes it outside my performance window and so I need to continue with other options. However, digging into the USB/HID API is in the correct direction so nothing lost.

regards

gordon

Replacing the PIC16C745 with a PIC18F2550 was simpler than I thought. You also need to replace the 6 MHz crystal with an 8 MHz one but otherwise the chip is pin compatible.

I loaded the Microchip USB bootloader onto the chip - I had to invert the sw2 setting as the Microchip DEMO boards pull down whereas the K8055 pulls up, and change the pin assignments for sw2 and the 2 status LEDS.

Now I have a Full speed USB 2.0 board that I can program “in-circuit” via the USB. I can work with the HID firmware to get the control I require.

regards

gordon

Hi, it looks like I have the same problem as Gordon, I have also carried out the link of Outputs to Inputs expecting a 1ms update but is typically 8ms. As I trying to synchronise to another circuit operating at 5ms intervals this is not very useful. I have 4 of these kits trying to run independently.

Ok, I understand that by swapping to the PIC18F2550 and 8MHz xtal then this fixes the USB/HID delay problem.
So

  1. can I buy replacement programmed chips? This is probably the simplest solution
    OR
  2. How do I proceed with programming one of these new PICs:
    a. I have a PIC programmer K8048 but it does not mention this device (and I need to build it up)
    b. Should I buy a Microchip Evaluation board?
    With either of these what procedure do I need to follow being new to PICs.

Thanks
TERRY

The K8055 is using the low speed USB communication. The response time is typically 8 ms.
As an alternative you may use K8061. It is using the full speed USB.
Also the VM167 is using full speed.

There is no PIC firmware update available for the K8055.

Hi thanks for the reply.
According to your K8061 specification sheet typical execution time is 48ms/21ms and “general” response time is 4ms. So does this mean
a transition on an Input takes 4ms to be recognised by the VB program
and then an Output in response takes 21ms execution time + 4ms,
a total time of 29ms?

Thanks

These values are for the old drivers in the “Vistapack” for the K8061:

  • standard execution time: 48mS (use Microchip and K8061D.DLL drivers)
  • enhanced execution time: 21mS (use K8061_C.DLL)

For the new driver the response time is typically less than 4ms.
As seen in the example in the previous post, the execution time for these two instructions is about 3.25ms per instruction:

reads = ReadAllDigital(CardAddr); OutputAllDigital(CardAddr, writes);

Here is the link to download the latest software package for the K8061/VM140:
[color=#000080]Complete software package edition 2011[/color]

The package includes new driver and new DLL.
There are example projects written in many programming languages included.

You have to remove the previous driver and install the new driver (v1.0.0.6) from this download package.
Please read the Getting_Started.pdf and the README.TXT

Ok thanks that’s very helpful.
I’ll purchase a K8061 and see how I get on.

Hi again,
Ok I have received and built an K8061, and the executable diagnosis and demo programs run ok.
So I browsed the Examples, and unfortunately I am using VB in MS Visual Studio 2005, your examples are for 2008 so I can not run these. I also tried the VB6 version which Visual Studio tried to convert/upgrade but failed with a binding error.

So do you have any VB2005 example software available that I could work from?

Thanks
TERRY

Here’s the link to download a K8061/VM140 example written in Visual Basic 2005:
box.net/shared/rrt8rlfdne

Great. Thank you very much.
TERRY :smiley: