Pages: 1 [2]   Go Down
Author Topic: fast serial sendin  (Read 5439 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 22
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

nope nothing there. this must be a windows vibe only i guess
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 22
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Just another point on this. I hadnt realised that ftdiport.inf is part of the driver download on windows. You must edit it before you install the driver on windows. I could find no equivalent on OS X though.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 22
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Heres a solution to the 4K block problem outlined in this topic. Solder a wire to X3 pad 1 on the arduino. This is the CTS pin on the ftdi chip. Toggling this pin will cause the ftdi to flush its send buffer up to the PC. Works like a charm. I connected this to pin 13 and set pin 13 high after a read through the analogues and low while waiting for an interrupt. Nasty. Can someone show me a really quick way to toggle each time throug the loop in hardly any code?

this code is now a complete mess but i'll clear it up later.

Mellis: I guess thats a use for X3  smiley

Code:
#include <avr/interrupt.h>
#include <avr/io.h>

#define INIT_TIMER_COUNT 6
#define RESET_TIMER2 TCNT2 = INIT_TIMER_COUNT

volatile int Ft = 1;
int int_counter = 0;
volatile int count = 149;
int oldcount = 0;
long starttime = 0;
long time;
long start;

int ledPin = 13;
int analogPin = 0;
int analogInputsEnabled = 4;
int i;
int analogData;            // outgoing ADC value
int n = 0; //index for digital read loop
int digitalPin;

byte x = 0; //byte to store digital pin status


// Arduino runs at 16 Mhz, so we have 1000 Overflows per second...
// 1/ ((16000000 / 64) / 256) = 1 / 1000
ISR(TIMER2_OVF_vect) {
  RESET_TIMER2;
  int_counter += 1;
  
  if (int_counter == 2) //set sampling frequency here 1 = 1kHz, 2 = 500Hz etc
  {
    if (count == 250){count = 149;}
    count+=1;
    int_counter = 0;
  }
};

void setup() {
  Serial.begin(115200); //setup serial
  Serial.flush();
  int resp = 0;
   pinMode(ledPin,OUTPUT);   // declare the LED's pin as output
  
  //set up the timer 2 interrupt
  //Timer2 Settings: Timer Prescaler /64,
  TCCR2A |= (1<<CS22);    
  TCCR2A &= ~((1<<CS21) | (1<<CS20));    
  // Use normal mode
  TCCR2A &= ~((1<<WGM21) | (1<<WGM20));  
  // Use internal clock - external clock not used in Arduino
  ASSR |= (0<<AS2);
  //Timer2 Overflow Interrupt Enable
  TIMSK2 |= (1<<TOIE2) | (0<<OCIE2A);  
  RESET_TIMER2;              
  sei();
            
            
  //enable digital pullups
  for(i=2;i<8;++i)
                   {
                digitalPin = i;
                    digitalWrite(digitalPin, HIGH); //enable internal pullups
                    }


 digitalWrite(ledPin, LOW);


}

void loop() { start = millis();

  digitalWrite(13, LOW);  
  if (oldcount != count) {
   /* get analog in, for the number enabled */
      for(analogPin=0; analogPin<analogInputsEnabled; ++analogPin)
      {
            analogData = analogRead(analogPin);
                Serial.print(analogData >> 7, BYTE); // shift high bits into output byte
            Serial.print(analogData % 128, BYTE); // mod by 128 for the small byte

      }

Serial.print(255, BYTE); // end of analogs signifier  
                
                
//digital pin checking stuff
               x = PIND >> 2;
             Serial.print(x, BYTE);
               Serial.print(count, BYTE); // a counter that runs from 150 to 250 to check for missing bytes
               Serial.print(254, BYTE); // end of digital signifier
                  
    //a timer to see how long through the loop;
    time = (millis() - start);
    Serial.println(time);
                
              
      }
    
    oldcount = count;
    digitalWrite(13, HIGH);
  }

« Last Edit: June 19, 2007, 12:11:55 pm by nickytl » Logged

Greenwood, Indiana
Offline Offline
God Member
*****
Karma: 0
Posts: 508
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It's pretty simple code but I don't know what library for USB they are using.

What use is this for the average user? I didn't know that the USB device on the board had an eeprom. smiley

Logged

If it was designed by man it can be repaired by man.

0
Offline Offline
Newbie
*
Karma: 0
Posts: 22
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've had the same problem - regular prints of data from Arduino, but bursts of data turning up in Flash, but of varying sizes. Wow, this gets pretty confusing pretty quick. Ok, the conclusion as I see it is there are 5 options:
  • Edit the ini file before installing the drivers on a Windows machine. Easy, but not platform independant, and not flexible (able) to be changed for different uses. Has this been verified to work?
  • Get a pin on the Atmel chip to directly trigger a flush on the FTDI chip. Not so easy (not sure I could do it with just the instructions on the forum), requires customised hardware (?) and lengthy code.
  • Recompile the FTDI drivers. Did I get this right? Is this an option? I don't think the complete process has been defined for this yet.
  • Trigger a flush by sending a signal (adjusting a register value?) to the FTDI chip from the COMPUTER end. Did I get this right? Sounds possibly easy, flexible, not require hardware customisation and possibly platform independent. But I don't think the complete process has been defined for this yet.
  • Trigger a flush by sending a signal (adjusting a register value?) to the FTDI chip from the ARDUINO end. Did I get this right? Sounds possibly easy, flexible, not require hardware customisation and definitely platform independent. But I don't think the complete process has been defined for this yet.

I'm not sure if I have got all of this right. Im keen for others to improve upon this summary, and maybe have it as a sticky at the start of the post or in the playground or something.

Cheers for all the hard work.

Eric
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 22
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have not researched this yet, but I have recently been looking at a different, dedicated system that pushes time-critical data on the USB bus. It is a robust, professional system, and they acknowledge the USB latency problem and have a solution. I'll quote from http://www.usdigital.com/products/seiusb/body_index.shtml#timingspecs
Quote
Data Latency: The USB data latency timer is preset to a default value of 16ms by the driver manufacturer. This means that data could be sitting in the FIFO buffer up to 16ms before it is forced to transmit. If Windows is allowed to search the internet for the device drivers when the "Found New Hardware" wizard is displayed, then the latency timer will be set to 16ms. The latency timer can be set to a minimum of 1ms using USBSpeedBoost software found on the product installation CD or here (http://www.usdigital.com/software/usbspeedboost). If the drivers are installed from the installation CD, then the latency timer will automatically be set to a minimum of 1ms.

So it sounds like they nailed it via a customised driver. I am not sure if USBSpeedBoostSetup.EXE is the driver, or is, as the quote suggests, some separate software. If it is separate software, then I'm not quite sure how it works - maybe it modifies the windows default driver that would be installed by the "Found New Hardware" wizard. Or maybe it adds its own driver to the Windows driver library so that it is installed instead.

Either way, it seems the driver option is a good way to go. As per the first option in the previous conclusion, it is easy, but not flexible and seems to be Windows specific. If must be in the other drivers somewhere too - has anyone tried searching for

I unzipped the 6mb (!!) USBSpeedBoost file. It is simply an exe file. I don't have the device it is designed for, but I ran it anyway. The installer did its thing, then reported "Attempted to update the latency timer setting for all US Digital virtual comm ports. No updates required". So it sounds like it can actually change the latency of the driver after the driver has been installed. This suggests flexibility can be pretty good - if we could figure out how to do what USBSpeedBoost does - after the driver has been installed...

Googling "USBSpeedBoost" only gets about 5 results, all referring to USDigital. Googling "USB SpeedBoost" gets a plethora of results that don't seems much use. So I guess it is a proprietay USDigital thing.
« Last Edit: February 28, 2008, 04:48:59 am by MindSpace » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 22
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am not a Linux expert by many long shots, but from what I can tell from the Arduino Install guide for Lunix, the FTDI drivers are already installed. At the very least, they do not come with Arduino 0010 for Linux.

So I grabbed the driver from http://www.ftdichip.com/Drivers/VCP.htm and took a look. None of the files contain "3f", however, 'ftdi_sio.c' contains:
Quote
#define URB_TRANSFER_BUFFER_SIZE      64 /* the device's max packet size */
/* Constant for read urb */
#define BUFSZ 512
#define PKTSZ 64
...
static int  ftdi_write                  (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
static int  ftdi_write_room            (struct usb_serial_port *port);
static int  ftdi_chars_in_buffer      (struct usb_serial_port *port);

And in ftdi_sio.h
Quote
#define FTDI_SIO_RESET_PURGE_RX 1
#define FTDI_SIO_RESET_PURGE_TX 2
...
 * The Purge RX and TX buffer commands affect nothing except the buffers
...
/*
 * FTDI_SIO_SET_EVENT_CHAR
 *
 * Set the special event character for the specified communications port.
 * If the device sees this character it will immediately return the
 * data read so far - rather than wait 40ms or until 62 bytes are read
 * which is what normally happens.
 */
#define  FTDI_SIO_SET_EVENT_CHAR_REQUEST FTDI_SIO_SET_EVENT_CHAR
#define  FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE 0x40
...

I don't know if this helps, but it seems that some of this could be modified a little before compiling.

I tried downloading the osx drivers, but I couldn't open the dmg file in Windows ;(
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 22
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
How fast are you sampling and how much data are you sending? The easiest way to reduce the burstyness is to reduce the sampling rate so your datarate doesnt exceed the threshold that causes it to be sent in 4k blocks.
The hardware solution I posted is really very simple. All you need is a soldering iron and a bit of wire and a bit of solder. Or ask someone else to do the soldering. Just attach about a 2 inch piece of hookup wire to x3 pad 1 on the arduino. X3 is the  set of 4 connections beside the ftdi chip on your arduino. TO attach a wire I simply put a very small amout of solder on the iron. I then touched this against the back of pad 1 and pushed in the bit of wire from the front into the melted solder.
Now connect the other end of the wire into one of your digital pin sockets and in your code toggle this pin each time you want to send data up to PC/flash. In my example youll seee I digitalWrite(13, HIGH) before reading my inputs and then digitalWrite(13, LOW) after. This solution gave me much smoother data in MAX/MSP.
Let me know if you need photos and I'll try and put up some.
Nicky

 
Logged

Brooklyn, NY, USA
Offline Offline
Full Member
***
Karma: 0
Posts: 115
arduino for all
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the info, photos are always helpful.  As for the hardware solution, it is good to have.  Ideally we could find a software solution so that it could be automatically incorporated into the arduino.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 22
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi nickytl,

As far as I can tell, I am trying to send about 6 bytes up to 250 times per second (4ms). I was going through the ss6 Java serial server to flash. I had flash trace the data with the millisecond it received it. It seemed to get nothing for a while, then get a burst of data of 4 to 40 readings all at once. Sometimes it gets a few values individually with no backups.

I am not so convinced now that I am only experiencing USB latency. 6*250 = 1.5k, so thats not the problem. I am guessing with latency I could expect bursts of 4 values, but not 40!

Unfortunately, it is a long chain, and any stage of it could be a problem, but I think I have alternatives to test at every stage now (FTDI Chip: X3 pad, USB Driver: Windows driver hack, Serial Server: serproxy, Flash: collect data in a different way).

Yeah, the X3 hardware solution doesn't look too hard. The soldering is not a problem. Wasn't quite sure what goes where - never heard of X3, and haven't got the board beside me, but those instructions sound pretty clear.

eighthave - I agree - tweaking a register value in the FTDI via software from the Arduino end sounds like the most elegant, OS independant, flexible solution, but hey I'll take the hardware solution quite happily for now.

Thanks for the clarification and help.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 1
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello all!
About Flash.
It seems I`m way too n00b for all this discussion, but from what i understand after a bit of testing, it is Flash messing up some stuff, for those who use it. I guess it doesnt depend on what proxy (serial/usb to socket/tcp), since i use "serproxy" on windows, pyserial on nokia n810 (linux) and i get the same results - on Flash tracing and just receiving gives wrong length data. sometimes it puts two lines together, sometimes it splits a single line into more, even sending the same line all the time (like "hey" translates to "heyhey" or "h" and "ey" on next line).
when i do just simple telnet to the socket/tcp port, it gives out every line correctly (i guess i`ve seen it loose a part of line, but that`s like 1% case).
Flash tcp reading also relies on the data transfer latency, if i read the port over wi-fi, it gets about 16bytes at a time, but if the serial and proxy is on the same pc as Flash, it`s fast enough to read 3-5byte chunks at a time (Flash: trace(arduinoSocket.bytesAvailable); arduinoSocket.readUTF8bytes(arduinoSocket.bytesAvailable))
btw i dont use Firmata, just simple Serial.println on arduino / echo testing. and actually i guess the "Flash" speed thing is totally offtopic to Ardiono <-> USB  smiley-grin
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 6
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Sometimes it puts two lines together, sometimes it splits a single line into more, even sending the same line all the time (like "hey" translates to "heyhey" or "h" and "ey" on next line).
What about his problem? Im facing similar issues...any updates so far?
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 8
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Again, when using the FTDI Virtual COM Port drivers the USB Transfer (buffer) size can be set in
the port properties page.  The initial buffer size is calculated from entries in the ftdiport.inf file - with
the size of buffer allocated being equal to the .inf entry plus 1 multiplied by 64 (bytes).
So 0 is 64 bytes, and 3F is (63+1)*64 = 4096.
There are two entries in the INF file - the first one is the transmit buffer and the second is the
receive buffer.
[FtdiPort.NT.HW.AddReg]
HKR,,ConfigData,1,01,00,3F,3F,10,27,88,13,C4,09,E2,04,71,02,38,41,9c,80,4E,C0,34
,00,
1A,00,0D,00,06,40,03,80,00,00,00,00
In the example above the two 3F's are the entries in question, with this line being set for 4k byte
buffer size operation and
[FtdiPort.NT.HW.AddReg]
HKR,,ConfigData,1,01,00,00,00,10,27,88,13,C4,09,E2,04,71,02,38,41,9c,80,4E,C0,34
,00,
1A,00,0D,00,06,40,03,80,00,00,00,00
being set for 64 byte buffer size operation.

I found these settings post-install by searching for the proper COM port name (COM5 for me) in regedit:

HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\FTDIBUS\VID_0403+PID_6001+A70063sHA\0000\Device Parameters

Then "Right Click / Modify Binary Data" the ConfigData key.
Logged

Pages: 1 [2]   Go Up
Jump to: