02-13-2019 09:35 AM
Hi everyone,
I hava an Arduino DUE and I have to generate a PWM to drive sensors, acquire data with ADC and then send to LabVIEW.
I have a problem while reading from Arduino and/or transmitting via Serial, during one or both steps my data are "corrupted". I tested the PWM wave both with Arduino ADC and with NI 6008. I found that with the 6008 my square wave was quite clean while with Arduino , it was totally wrong.
I do not know if the probelm is my LabVIEW file or ADC itself or even communication via serial, I have not even figured out yet what is the cause of the problem, for this reason I ask you if someone knows what may be and if can help me.
I attach my two waves (one with NI6008 and DAQ assistant and one with Arduino and the block diagram) and LabVIEW.
Thank you very much!
Solved! Go to Solution.
02-13-2019 09:53 AM
What is the PWM frequency?
What is the sampling frequency?
How often do you transmit and what does the serial packet contain?
Can you show part of the sketch so we can see how you are attempting the acquisition and sending?
I suspect that the serial communications are the sticking point, but its a guessing game right now.
0xDEAD
02-13-2019 10:05 AM
Thank you for your reply. Sorry, I forgot to attach the code.
PWM frequency is 525 Hz and Sampling with NI is 10Khz, while with Arduino I did not set a precise ADC frequency but I mesured it and it is 20KHz (each entire loop takes a bit less than 50us).
I am sending 2 values (the 2 read analog values) as uint16 at baud 460800 and as binary data.
#define PWMFreq (525); #define DutyCycle (0.66); uint16_t val[2]; int16_t carrier = 0; uint16_t RegPWM = 328125/PWMFreq; uint16_t RegDT = (int) RegPWM*DutyCycle; void setup() { Serial.begin(460800); while(!Serial); pinMode(22, INPUT); REG_PMC_PCER1 |= PMC_PCER1_PID33; // Enable peripheral TC6 (TC2 Channel 0) REG_PIOC_ABSR |= PIO_ABSR_P26 | PIO_ABSR_P25; // Switch the multiplexer to peripheral B for TIOA6 and TIOB6 REG_PIOC_PDR |= PIO_PDR_P26 | PIO_PDR_P25; // Disable the GPIO on the corresponding pins REG_TC2_CMR0 = TC_CMR_BCPC_SET | // Set TIOB on counter match with RC0 TC_CMR_ACPC_SET | // Set TIOA on counter match with RC0 TC_CMR_BCPB_CLEAR | // Clear TIOB on counter match with RB0 TC_CMR_ACPA_CLEAR | // Clear TIOA on counter match with RA0 TC_CMR_WAVE | // Enable wave mode TC_CMR_WAVSEL_UPDOWN_RC | // Count up with automatic trigger on RC compare !PHASE_CORRECT! TC_CMR_EEVT_XC0 | // Set event selection to XC0 to make TIOB an output TC_CMR_TCCLKS_TIMER_CLOCK4; // Set the timer clock to TCLK4: /128 (MCK/128 = 84MHz/128 = 656250Hz) REG_TC2_RA0 = RegDT; // Load the RA0 register 66%DT REG_TC2_RB0 = 0; // Load the RB0 register : -- REG_TC2_RC0 = RegPWM; // Load the RC0 register as 656250/RegPWM/2(per la phase-corr) = freqHz REG_TC2_CCR0 = TC_CCR_SWTRG | TC_CCR_CLKEN; // Enable the timer TC6 analogReadResolution(12); } void loop() { //float srt = micros(); carrier = 2*digitalRead(22)-1; val[0] = analogRead(A0); val[1] = analogRead(A1); Serial.write(val[0]); Serial.write(val[1]); }
02-13-2019 02:13 PM
Most likely, you are just reading your data out of sync. As I told you in your other thread, you need a true message protocol to avoid this kind of issue (ie make sure you have a complete message). When sending your data, first send a 0x2 (in ASCII, this means Start Text). Then send your two data points followed by a checksum. The checksum can be something as simple as adding all of the data bytes in your message, resulting in a U8. Then on the LabVIEW side, you just read 1 byte until you read that start byte. Then read 5 bytes (2 I16s and the checksum byte). Add the data bytes together (Add Array Elements) and verify it matches the checksum byte. If it does, process the data as you already are doing. If not, don't process and go back to looking for the start byte.
02-14-2019 02:01 AM
Thank you for the reply, but I do not know how compare my first "read buffer" with the start of text I am sending. I know I have to use "equal?" block, but inputs of that block are read buffer from the visa and... the string "STX"? The hexadecimal number 0x02? Its decimal form?
Then I have a question for the sync, If I read something wrong, I am losing the entire data for that loop, is there a way to avoid it?
Here is what I am doing. Actually, I do not know if it is good ( the "equal?" of the STX is not connected).
Thank you for your time
02-14-2019 02:50 AM - edited 02-14-2019 02:54 AM
I am intrigued by the 480600 BAUD. Whats the story with that? Do the devices at both ends support it?
Crossrulz suggestion of making a packet structure is always a good one if you can tolerate the overhead.
Also, I'm not convinced that you can send 16 bit values using Serialwrite. I suspect it will truncate to 8 bits as it expects either a byte or a string.
I would try something like the below, see if it helps:
Serial.write(val[0] >> 8);
Serial.write(val[0]);
Serial.write(val[1] >> 8);
Serial.write(val[1]);
0xDEAD
Edited to add: I can't view your VI as I am on 2015 here. If you could re-save for my previous version I will happily take a look.
02-14-2019 03:59 AM - edited 02-14-2019 04:00 AM
The baud rate is due to the fact that I have to send at the highest rate which does not generate garbage, I tested it via ASCII print and it transmits "correct numbers", and the exact baudrate is that I tested using TeraTerm and it has preset values, and 460800 was the highest among those.
About Serial.write, you are right about that but it did not solved the problem, I am trying to set the protocol but I am stuck. I attach the .vi for previous versions, let me know if you can see it.
I have a question about the shifting in serial.write, am I sending my bytes like it was Big Endian?
Thank you.
02-14-2019 04:21 AM
I cant open the VI (still says 2018).
The byte order in the received string would be big endian.
For example hex string 0FD00FD0 would be 4048 from AI0 and 4048 from AI1
0xDEAD
02-14-2019 04:41 AM
I saved it for previous version 15, I hope it will be fine
02-14-2019 05:15 AM
Something like this should prove if it works or not. Then you can add what you need later.
(Probably best to replace AI0 and AI1 indicator with charts).
0xDEAD