So this program I have been playing with is interesting. There are two registers on the controlled device that have to be set to run at 1.6 kHz, being R11 and R12.
Set to 80 hex, which is something in bit form.
The serial port sniffer tells me the original code makes 156 calls to five different registers to make two settings.
It is likely that additional setup is being performed other than (in addition to) setting the 1.6kHz.
Can you say what the device is? Manufacturer, model, and any other information?
What is it doing for you? Is there an alternative that you could use or build?
You might be surprised what you can build today for an handful of dollars.
It is an ST MKI210V2K controlled by an ST MKI109v3 controller. It runs over a USB cable reconfigured as a USB Fake Port.
The sniffer gets all of the traffic, I can read all of the registers so I can check the configuration.
The resolution is good at 60 microg, as the thermal layer is 0.1 to 0.3 mg, there is good accuracy on the readings.
But the max speed is 400Hz or thereabouts. The controller is about 90 and the accelerometer about 30. Although 400 Hz will give me an FFT of 200 Hz, which is not bad for the real purposes.
I am looking at alternatives, first I had to write a program to access the device.
USB 1.0 speed is up to 1.5Mbps
USB 2.0 speed is up to 480Mbps
Check to see if you are connecting via a USB 2.0 port.
It supports both I2C and SPI protocols.
Using the USB port, this would (my assumption) be using I2C protocol. This is a 2-byte protocol (address+data). ~20 bits into device+latency+20 bits (or more) out of device, at least 40-bit times. USB 1.0 +1.5Mbps/40 = (at most) 37.5Ksps, though there may be a block sampling feature resulting 2x or 4x this sample rate. This does not account for any potential USB protocol overhead.
This seems to indicate that your connection is via USB 2.0. Or at most a potential sampling rate of 12 Msps (diminished by internal latencies of the device and USB target side and USB host side).
The link above shows it is using ISM330DHCX accelerometer (not listed on the ST website). This may be a problem with the web page. Digi-Key lists the component. The datasheet shows linear acceleration output data rate of up to 6667Hz. I am not sure what the limiting factor pegging you at 400 Hz.
The device has both I2C and SPI interfaces.
SPI interface does not require an I2C device address byte, and the maximum clock frequency is 10MHz, additionally SPI is full duplex (send and receive at same time with a skew between the data (register) requested and result returned.
This would provide more flexibility as you could buffer the samples internally or to attached SD card then download data either concurrently or later. Also via WIFI and different IP addresses it would be QED to setup multiple sensors (at relatively low cost).
You make more sense than the ST web site. Thanks for the comments.
I wanted to try and see if I could find an accelerometer that measured below the thermal layer. The thermal layer is between 0.1 and 0.3 mg depending on the temperature. This is the effective limit for all readings on an accelerometer.
The accuracy I have with the current machine is about 50 microg - which is good.
I talked to ST and they suggested the 210. It was cheap and the interface card was cheap so I bought both about ten days ago. I want to plug this thing into an existing environment, but ST does not provide a simple reader for the accelerometer. They provide UNICO that is a logged down dog. And a sample UNICO lite that actually does not do anything, but open the port.
I checked with the UNICO - GUI and it also reads at 145 cycles per second over a long recording time. Even when you set it to 1666 Hz.
There is clearly something wrong in the GUI that is not setting the correct registers for the read speed.
I will look at your suggestions as soon as I get this other stuff finished.
Often the terminology used in a datasheet does not match the terminology of the implementer. From my read, I think you want to use Continuous Mode .AND. assure that you read the FIFO at sufficient speed/intervals such that it does not overflow.
FYI, my interpretation of a FIFO is that it has a capacity and that it presents a ring buffer. As long as you read before the ring buffer gets past full, the FIFO is suitable for infinite amount of data. Their description of "FIFO mode" appears to describe the buffer usage as being filled off-line, sampling paused, then read on-line, sampling off-line begun again, paused, read, start, pause, read,...
but who knows until debugging.
You may be able to locate Application Notes and or other sources showing sample code., should you decide to go the DIY route.
If you need help, you have my email address.
I think I have cracked it, I am running at 1600 hz.
Once I started the FIFO, I just had to read it at an acceptable rate, I can read about 6500 bytes and then it overruns itself and I loop, it catches up and does not give me all zeros. The buffer comes back wtih a mass of data - you need to break into 14 byte blocks and get rid of the corrupted blocks. It does not have a constant length.
I was doing a check on 3A and 3B at each buffer read and it slowed the process down by 50%.
115 and 116 are st, which is the company name, why not just use one delinator. The first six numbers are X Y and Z acceleration, the 35, 2 might be the timer and the 13 10 is likely the temperature.
In reality it would be a lot more efficient to store this data instead of the translation into doubles and then store a lot of excess numbers.
Thanks your find saved me.
I threw in the routines to do the hex to real conversions and the code speed went to 500 Hz. The processor in the NUC core i3 in a single thread cannot run the code fast enough.
Is it better to just wait to the data collection is finished or could I throw the data into a second thread to do the conversions?
Glad to hear of your progress.
Your X. Y Z values appear to be presented using 3 bytes. I do not know what negative values are. Can you show me one example of a negative acceleration?
Is the data returned as binary or as ASCII digits as shown above, IOW is the above the printout of returned data inclusive of comma and space .OR. is that an artifact of a binary to decimal formatting of a program you wrote?
The conversion from binary to REAL should be relatively painless (provided you can illustrate a negative value).
One thread should be able to read the buffer and convert (assuming you do not write to file).
If writing to file, use two threads:
One to read data and store into a ring buffer (aka your own FIFO), and the second thread to convert to real and store into file. Your buffer (your FIFO) need be large enough to accommodate any disk latency (system I/O and/or any other mischief).
The device FIFO should be large enough to handle any Windows mischief (preempting thread to run something else). You can mitigate this by using the task manager to raise the priority of your process. If you get drop outs, you may correct this by inserting an MPU, with sufficient memory, to handle the Windows mischief.
The acceleration data comes as sets of two bytes, sample X 0 96 Y 254 59 Z 64 154
The program uses a bit to int16 convertor, and for the above typical results when mutlipled by 0.061/1000.0 we get g.
We get zeros from the return about 10% of the time, I have to filter those out yet.
I have never played with bit to int converters so I have no idea how they work, as Oddball said in Kelly's Heroes,
Big Joe : Well, then, why the hell aren't you up there helping them?
Oddball : [chuckles] I only ride 'em, I don't know what makes 'em work.
So at least I now know they are fit for purpose, now we have time to solve the other problems.
Thanks for the thread stuff,
SAMPLE FROM THE MAKERS GUI - different location on a desk not on a beam.
|A_X [mg]||A_Y [mg]||A_Z [mg]||A_X [deg]||A_Y [deg]||A_Z [deg]||G_X [dps]||G_Y [dps]||G_Z [dps]||TEMP [C]|
I haven't fully read, and understood, the datasheet for options, this said, the 15 byte records shown earlier (including sequence number, 'S', 'T'', Return, Linefeed) leaves 10 bytes of data. This seems insufficient to report the values in the table immediately above. Therefore, it appears that you can specify a filter to indicate what data is to be returned. My suggestion for least possibility of dropouts would be to set the filter to return only the data you want, with one thread read those reports into a double buffer system using one thread, and the second thread, for example, writing the INTEGER(2) Ax, Ay, Az records to a log file. If you create/open the log file with shared access, you can have a separate process displaying progress and/or charts, status, etc...
Of course, the 10 and the 13 are the cr and lf, teh obvious can be difficult to see.
The current set of bytes only return the acceleration, I am not interested in the gyroscope, but I want the temperature.
Good way to spend Saturday.
The notes you found included a message as to what to try if the device slowed up.
You cannot do the conversions in the same thread, it just blocks the reads and slows everything up. So onto the threading.
Each buffer is 30 bytes long, at the moment the last sixteen are zeros.
In the 12th byte there is a string set that graphs with time as
It repeats every 32 steps - do you think this is a timing thing?
The temperature is logged about 10 times per second and is send as a a separate buffer.
Still cannot find gyro or timer output.
>>You cannot do the conversions in the same thread, it just blocks the reads and slows everything up.
That doesn't make sense to me. I'm making here that:
1) You can read the FIFO buffer count (count being number of bytes or number of records).
2) there is a command that instructs the MPU to return one record from the FIFO
3) you write a "Get record from FIFO" to the MPU
4) you receive one record of data (or some error condition)
With the above in place
! pseudo code loop1: n = getNumberOfRecords() ! returns 0, # records or -error code if(n<0) handleError() if(n<2) goto loop1 SendReadOneRecordCommand() ! but don't read the data yet loop2: SendReadOneRecordCommand() ! 2nd read request errCode = readOneRecordOfData() ! read the first record if(errCode<0) handleError() convertData() ! no write to file if(recordsRead<recordsWanted-1) goto loop2 errCode = readOneRecordOfData() ! read the first record if(errCode<0) handleError() convertData() ! no write to file ! have data
IOW the conversion occurs during the transmission time of the next read record request. This is free time.
As long as your code does not write to the file, this should work.
This said, if the chart shows the error? blips, then something else is going on (and will take closer investigation).
I have the GUI program written in C by the manufacturer ST.COM.
I checked that that if I use the settings I am using for 1666 Hz read time, and I use their GUI program I get 400 Hz read speeds. They are doing the conversions in their program.
In my program if I just read the data and push the bytes to a csv file I get 1666 give or take about 10 Hz. If I add the conversions to the same thread I get 400 Hz.
I read the date in 16384 blocks so I just write to the screen at 16384 blocks which should take 10 seconds and it is ok with no conversions. I have just about got the second thread working. The blasted bytes were interesting to store in the first thread in an array I could push to the second thread. I kept getting the same value in all the cells of the array.
It is a lot faster to just read in one go the entire buffer and not a single record and take the buffer apart, multiple reads to the device slows it up. If I do an enquire before the read buffer read I get 800 Hz. There is a note in the document about the device slowing up.
The link above shows a neat little instrument. The German video provides a neat explanation.
Anyway it is a lot of fun and thanks for the help
The interesting problem is the timing, the computer clock is accurate to 10 to 15 milliseconds only on sequential reads.
I think the jagged chart above is the way to tell you when the signal was read.
If we are reading at 1666 Hz then that is once every 0.6 milliseconds.
Interesting problem, has anyone run across this before?
You should specify the chart axis and how they were produced.
I assume X was sample number and Y time in ms between samples....
.... however, the chart behavior indicates the simple interval was obtained by the thread performing the writes to the disk file as opposed to by the thread performing the read from the USB port...
Please note that in the FIFO mode (my assumption is) your device is configured to sample at a specific frequency, either continuously or for a specific number of samples. And it is the host's responsibility to empty the FIFO before it reaches capacity. In this situation, the time you record in the host (NUC) on read from USB does not reflect the time interval the sample was made. From (hazy) recollection of the datasheet, an 8-bit rollover sample counter is sent with the data (i.e. the lsb of the sequence number). This can be used to determine if the FIFO overflowed or other thing internal to the device failed to capture a sample. At least this is how I would expect this to be.
My apologies. The graph shows the numbers coming from a single register at 1666 Hz. They are some sort of timing thing.
I am using a Serial Port Sniffer to look at the to and fro from the device.
I have been using the console view, but there is a packet view which shows stuff that does not appear in the console view.
I am getting back a packet of 14 bytes, I need to increase this to at least 30 bytes to get all the data I need, as the GUI program does.
Interesting learning experience. Unfortunately other things interfere in the learning process.
Completely aside, but I have been reading a murder mystery. It appears that champagne and Sodium Bicarbonate is not something you should drink. Interesting things you learn in your daughter's novels. These books are a great way to learn chemistry for fun, I wish I had had them in high school, the author makes chemistry make sense.
Pity we do not have a Fortran equivalent.
(It raises the pH of your blood to 7.5, which is both painful and fatal.)