I have connected a device which sends data over a serial port, through UART and a usb connector.
On my laptop running ubuntu, I have written a C++ program to read this data and store it.
It sends 5 lines of 15 bites, 100 times per seconds, meaning: 500 lines per second.
I use the standard read command:
while((res += read(IMU, header, 15-res)) < 15);
string head(header, 15);
cout << indexLog << " " << head << endl;
when I read the serial port and read 15 bites it shows:
0 snp�` �����
0 snp�b#A��H
0 snp�dP�O�^���
0 snp�\����f
0 snp�^���e��M
0 snp�` �����
0 snp�b"����
where the snp is the beginning of each package. It can be seen that my laptop nicely reads every bite coming in, since every line starts with snp.
I would like to run the same application on my Raspberry PI, for weight and size considerations.
now when I run the same application on my raspberry PI, I get:
0 �Nsnp�Nsnp
0 Nsnp�\��
0 vsnp�^���
0 np�^�O�
0 vsnp�^�O�
0 np�^�D�
0 ssnp�
0 X�snp�dU
It looks like the raspberry doesn't read all the bites, and it becomes a big mess. Trying to salvage usefull date results in big data loss.
I all ready installed a skimmed down version of Rasbian, weezy. deinstalled X as GUI. But it doesn't seem to make difference.
I believe the raspberry should be fast enough.
What would be the limiting factor?
Is reading 500 lines (15 bites) per second over a serial just to much to cope with for the RasPI?
Are there any settings I can change or OS for the raspberry which can do the job better?
Or is there a way in C++ to read the data more efficient?
kind regards
Is reading 500 lines (15 bites) per second
That is 500 x 15 x 10 = 75000 bits per second. Clearly that is not possible when your baudrate is only 38400. So transmitter overrun is your first candidate for data loss.
You also have a fire-hose problem on the receiving end. Your terminal needs to be able to keep up with the rate, 500 lines per second is pretty challenging. Scrolling the window fast enough is the usual problem, not to mention the poor eyes of the user that needs to stare at this Matrix effect. This is the more likely source of the data loss, when you don't empty the serial port receive buffer quickly enough then you'll suffer from buffer overflow. It can also occur when the driver doesn't empty the UART fifo buffer quickly enough, less likely to be a problem at 38400 baud.
The obvious way ahead here is to improve your code so that you can actually detect these kind of errors so you know when it goes wrong.
Related
I have an older Aanderaa RCM9 (https://epic.awi.de/id/eprint/45145/1/RCM9.pdf) that is missing its Data Storage Unit and its reader. They don't produce these anymore nor do they service the model. It would be a shame to toss an otherwise nice piece of equipment, so I thought to try and get a serial feed from the terminal or DSU output and log on an Arduino with an SD card. I have tried to connect with a TTL-RS232 converter, and there seems to be a consistent Tx from the instrument, it comes in batches, but reads out in CoolTerm as "............" I've tried different terminal configurations, and connections, but that's the best I get. Here's how it looks inside: https://imgur.com/a/xxCPUlQ
Any thoughts??
I am afraid that the output is the old Aanderaa PDC4 serial format where long pulses (81ms) represents zeros and short (27ms) represents ones in a 10 bit binary word framed in a 4 second window.
I recently got hold of a ZX Spectrum +3 and am trying to get RS232 working with the spectrum. I’ve built a cable (‘BT’ style connector <-> DB9 serial) following the pin out of the cable (Spectrum 128 RS232 data cable) here.
The other end of the cable is connected to the PC using a USB-Serial adapter. I'm using Moserial on Linux to communicate with the Spectrum.
The cable works and I can use LLIST to print BASIC programs over the serial port, but I'm unable to get the Spectrum to read from the serial port reliably - even when enabling hardware handshaking (DTR/CTS) in Moserial.
I wrote a simple program in +3 BASIC to print received characters to the screen. It seems the first character is received OK, but the remaining characters are dropped or become corrupted.
Here is an example of what the Spectrum outputs when attempting to send 'zx spectrum' at 300 baud:
z[dot/box character]. VAL$ [box character]MOVE VAL$ VAL$ ?)
(it seems VAL$ and MOVE$ are each a single character in the Spectrum's ROM)
screenshot:
And the BASIC program which opens the serial port, and prints received characters to the screen:
10 FORMAT LINE 300
20 FORMAT LPRINT "r"
30 FORMAT LPRINT "e"
40 OPEN #4,"p"
50 PRINT INKEY$#4;
60 GO TO 50
I discovered that if I send characters one-by-one from the PC with a long enough delay between them, I can get a much more reliable output from the Spectrum. I tested this with different delays, and 80ms worked the best. I don't really want to use this approach as a solution - it's awfully slow and occasionally some characters are dropped.
Could this be an issue with the Spectrum itself? Or am I missing something in my setup? Something just doesn't seem right, I know there is a program loader for the spectrum over serial - so surely the spectrum must be able to accept serial input without a 80ms delay per character?
The ZX Spectrum Interface 1 works by bit-sampling, in a software loop, with delays, so that it can look for the start bit and then look for the other bits. There is no shift register. It's all done in software.They don't even use interrupts or some other kind of fixed external timer to generate baud rate delays.
As a result, it doesn't even start looking for a start bit until it knows you're looking for input... Now that you have an idea what's going on I'm pretty sure you've already seen the problem there? If you're sending data too fast, then your basic program doesn't even have time to go back to the receive routine to look for start bits, and start bits are going to be lost, or more likely, you're going to pick up a bit transition mid-byte and receive gibberish... So you need to make sure that there's a delay between bytes and your Spectrum is ready to receive the next byte before you start transmitting.
Hope this helps even though it's a while ago, but others will find this so...
In zx spectrum 48k, with interface 1, i must choose how the rs232 will work.
Mode t : text ->rx and tx only character in 7bit
Mode b: byte -> rx and tx full byte (8 bit)
Maybe you must chek that.
On 48k with interface 1
FORMAT "b";9600
Then , the spectrum works in 8bit data at 9600 bauds.
In your code, i dont see how will works.
My best regards.
I came across your problem as I was trying to do the same!
You need to enable RTS/CTS handshaking in your linux (PC) application, not DTR/RTS.
This works for me on my Spectrum+2:
100 REM ** Receive Test **
110 REM ** Use RTS/CTS **
120 CLS
130 FORMAT "p";9600
140 OPEN #4,"p"
150 PRINT INKEY$#4;
160 GO TO 150
There's software incompatibility between modern computers and ZX Spectrum when doing serial communication. It can be fixed, but not from Basic. The problem with RTS/CTS is that after Spectrum signals that it can't receive any more data via the CTS signal: modern UART chips will assume that the receiving computer is still able to receive cca. one buffer of data (=up to 32 bytes). But ZX Spectrum only has 1 byte buffer. So when Spectrum says its' full, it will get flooded by additional 32 bytes of data.
That is the reason anything faster then 1200 bauds will not work from BASIC. However ... I got ZX Spectrum to run reliably at 57600 and with error correction at 115200. By simply expecting up to 32 bytes after I signal the PC to stop sending data.
I've had all this working years ago with my Spectrum and the ZX Interface 1's own rs232 port, but I wrote some C program using an old Windows 386 computer.
I still have the hardware and the cables. In fact, now that I remember I had to build my own "null modem" cable and connect it from the RS232 port on the computer to the ZX Interface 1 (I have an old Sony Vaio laptop with an RS232 port).
I was even able to download TAP files to play on the real spectrum. I'll dig up what I have and get back to you.
My hardware currently has four sets of sensors that I treat as four separate serial ports with receive functionality only enabled wired to the lower 4 bits of port 0. I have attempted numerous times to retrieve the correct serial port data (by aiming the lazer direct at the sensor) without success. I then researched that for more reliability, on a standard UART, each bit is sampled at 16x a second (I found this 3/4 down the page on https://www.allaboutcircuits.com/technical-articles/back-to-basics-the-universal-asynchronous-receiver-transmitter-uart/).
So I ended up rolling off my own version of that but due to my timings, my count is more like 32x a second, but that's ok.
I'm going to explain what I did first so everyone understands what is going on.
code explanation
I have four consecutive address locations setup to point to values of counters for each bit. Four bits are read simultaneously from hardware and a counter for that bit goes up or down based on whether that bit is set (light detected on that group of sensors) or clear (light not detected). This loop executes frequently at about a 9600bps speed.
The second loop only executes when a value is needed. This happens once every 16 times that the last loop executes (more like at a 600bps speed). It takes the counter value of each bit as if it was a signed number and uses the MSB value as the final value of that bit. Those MSB values get crammed together to form the official bit read from the sensors.
Is this approach OK to reliably determine whether the bit value is set or cleared?
And could I somehow redo this code so the processes run faster? because each loop consumes a large number of clock cycles (32 to 40) and if I can get it down to maybe 20 clock cycles, I'd be happy.
Also, this code is executed on AT89S52 microcontroller so I'm using its extended memory addresses.
the code
;memory is preinitialized to nulls
LAZMAJ equ 0E0h ;majority counters start address (end address at 0E4h)
MAJT equ 20h ;Majority value at bit address
mov A,P0 ;get bit values from hardware
mov R1,#LAZMAJ ;go to start of pointer
;loop uses 40 clock cycles out of 192 available
countmaj:
rrc A ;get bit
jnc noincmaj
inc #R1 ;bit is set so add 1 to counter for that bit
noincmaj:
jc incmaj
dec #R1 ;bit is clear so subtract 1 from counter for that bit
incmaj:
inc R1 ;move pointer to next bit
cjne R1,#LAZMAJ+4,countmaj ;see if pointer is out of range
;it is so end loop
;loop uses about 32 clock cycles and executes when we want data
mov R1,#LAZMAJ+4 ;go to out of range position
chkmaj:
dec R1 ;decrement pointer first so we are within range
mov MAJT,#R1 ;load value to majority variable. treat it as signed
mov #R1,#0h ;clear value from memory space
mov C,MAJT.7 ;Take sign and use that as carry
rlc A ;and put it into our final variable
cjne R1,#LAZMAJ,chkmaj ;if pointer isn't in first address then keep going
;otherwise exit loop and A=value we want
I face a big challenge to justify the performance of the following snapshot of my code that uses Intel MPI library
double time=0
time = time - MPI_Wtime();
MPI_Win_lock(MPI_LOCK_EXCLUSIVE,0,0,win_global_scheduling_step);
MPI_Win_unlock(0,win_global_scheduling_step);
time= time + MPI_Wtime();
if(id==0)
sleep(10);
printf("%d sync time %f\n", id, time);
The output depends on how much will rank 0 sleep.
As the following
0 sync time 0.000305
1 sync time 10.00045
2 sync time 10.00015
If I change the sleep of the rank 0 to be 5 seconds instead of 10 seconds, then the sync time at the other ranks will be of the same scale of 5 seconds
The actual data associated with the window "win_global_step" is owned by rank 0
Any discussion or thoughts about the code would be so helpful
If rank 0 owns the win_global_step, and rank 0 goes to sleep or cranks away on a computation kernel, or otherwise does not make MPI calls, many MPI implementations will not be able to service other requests.
There is an environment variable (MPICH_ASYNC_PROGRESS) you might try setting. It introduces some big performance tradeoffs, but it can in some instances let RMA operations make progress without explicit calls to MPI routines.
Despite the name "MPICH" in the environment variable, it might work for you as Intel MPI is based off of the MPICH implementation.
I am relatively new with Arduino and I want to:
Set the frequency of the IMU to 100 Hz.
Synchronise GPS and MPU6050 in order to get data at the same time:
1 set of IMU data and 1 set of GPS data ->
99 sets of IMU data. (//1 second) ->
1 set of IMU data and 1 set of GPS data->
99 sets of IMU data (// 2 seconds)
I can't find anything that I can use/understand.
There are several lengthy threads in the Arduino forums for the same kind of project. Here's a good starting point. Then check out powergravity's other threads here, here, here and here. The last version of his program is here. You've got a lot of reading to do. :)
It's difficult to summarize this information into something a "new Arduino" user can "use/understand", but I'll try:
The IMU and the GPS run off their own clocks; you can set the frequency, but you can't set when they happen. Their phases or time offsets could be different. The IMU could run slightly faster or slower than 100Hz, because it is based on its own oscillator, not the GPS atomic clock (in orbit).
There will be an average of 100 IMU samples per GPS data point (an exact 1000ms). But because the IMU and GPS are not synchronized, you may get 99 or 101 IMU readings for each GPS data point.
You don't explicitly state what you are doing with the data. Whatever that is, it must accommodate the different numbers of samples per GPS period. I recommend that your loop structure is based off of the GPS time. You can even use it to measure the true frequency of the Arduino crystal (and thus the micros() clock).
At these rates, you will need to choose your GPS serial port wisely. Here are some tips.
You will also need an efficient GPS parser. My NeoGPS library is smaller, faster, more reliable and more accurate than all other libraries.