random corrupted data in serial Arduino - serialization

I have issue to read serial data from Arduino Uno in UWP C#. Sometimes when I start app I get corrupted data.
But in arduino monitor always is good.
Corrupted data is like this:
57
5
But should be 557.
Arduino codes:
String digx, digx2, digx3, digx1 ;
void setup() {
delay(500);
Serial.begin(9600);
}
void loop() {
int sensorValue = analogRead(A1);
sensorValue = map(sensorValue, 0, 1024, 0, 999);
digx1 = String(sensorValue % 10);
digx2 = String((sensorValue / 10) % 10);
digx3 = String((sensorValue / 100) % 10);
digx = (digx3 + digx2 + digx1);
Serial.println(digx);
Serial.flush();
delay(100);
}
And windows universal codes:
public sealed partial class MainPage : Page
{
public DataReader dataReader;
public SerialDevice serialPort;
private string data;
private async void InitializeConnection()
{
var aqs = SerialDevice.GetDeviceSelectorFromUsbVidPid(0x2341, 0x0043);
var info = await DeviceInformation.FindAllAsync(aqs);
serialPort = await SerialDevice.FromIdAsync(info[0].Id);
Thread.Sleep(100);
serialPort.DataBits = 8;
serialPort.BaudRate = 9600;
serialPort.Parity = SerialParity.None;
serialPort.Handshake = SerialHandshake.None;
serialPort.StopBits = SerialStopBitCount.One;
serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000);
serialPort.WriteTimeout = TimeSpan.FromMilliseconds(1000);
Thread.Sleep(100);
dataReader = new DataReader(serialPort.InputStream);
while (true)
{
await ReadAsync();
}
}
private async Task ReadAsync()
{
try
{
uint readBufferLength = 5;
dataReader.InputStreamOptions = InputStreamOptions.Partial;
//dataReader.UnicodeEncoding = UnicodeEncoding.Utf8;
var loadAsyncTask = dataReader.LoadAsync(readBufferLength).AsTask();
var ReadAsyncBytes = await loadAsyncTask;
if (ReadAsyncBytes > 0)
{
data = dataReader.ReadString(ReadAsyncBytes);
serialValue.Text = data;
}
}
catch (Exception e)
{
}
}
}
My idea was if it happened, Program skip that data. I tried different buffer length but more or less than 5 will always receive incorrect.
Thanks for any help.

Two methods that can fix your problem.
Method1: Make your UART communication robust
That there is no chance of an error but this is a tricky and time-consuming task in the case of windows software communicating with Arduino.
But still have some tricks which can help you because I have tried them and some of them work but please don't ask for the reason why it works.
Change your UART baud rate from 9600 to something else (mine if works perfect at 38400).
Replace Serial.begin(9600); to Serial.begin(38400,SERIAL_8N1)where 8 is data bit, 1 is stop bit and N is parity none in SERIAL_8N1. And you can also try different settings in data bit, stop bit, and parity. check here
don't send data after converting it into a string Serial.println(digx);. Send data in form of bytes array use Serial.write(digx,len);. check here
Method2: Add CRC Packet
At the end of each data packet and then send. When it reaches the windows software first fetch all UART data then calculate CRC from that data and then just compare calculated CRC and received CRC.If CRC matches then the data is correct and if not then ignore data and wait for new data.
you can check for CRC calculation its direct formula base implement and for little head start check this library by vinmenn.

I used two things to fix the problem,
1. In Windows codes added SerialDevice.IsDataTerminalReadyEnabled = true property to read bytes with correct order. From Microsoft docs
Here's a link!
2. As dharmik helped, I used array and send it with Serial.write(array, arrayLength) in Arduino and read them with dataReader.ReadBytes(array[]) and right buffer size in Windows app.
And result is so stable even with much lower Delays.

Related

NAudio: Outputting an audio stream at high sample rate results in dropped and choppy sound

I am reading samples from a software defined radio device that delivers two channels of Int16 (shorts) that represent audio. I am trying to send this stream to an audio output device on a PC.
I already have this working with a different set of tools but would like to use NAudio in its place since there are other capabilities I could use.
The code starts with the software defined radio method placing an array of shorts (i.e. int16) arranged as left channel then right channel. The array size is 65536, the sample rate is 192,000.
When the packet is received it is place on a Blocking collection to be picked up by a thread that sends out the audio.
So for the purpose of this question, the thread starts by reading the blocking collection which returns 65536 shorts.
StartStream = true;
waveformat = new WaveFormat(192000, 16, 2);
bs = new BufferedWaveProvider(waveformat);
bs.BufferLength = 65536 * 4;
_waveOut.DeviceNumber = 4;
while (true)
{
dspPacket = dsp_Queue.Take(); //take int16[] of queue
int j = 0;
try
{
for (int i = 0; i < 32768; i += 2)
{
byte[] qDataByte = BitConverter.GetBytes(dspShort[i]);
dspBytes[j] = qDataByte[0];
dspBytes[j + 1] = qDataByte[1];
j += 2;
}
if (startStream)
{
bs.AddSamples(dspBytes, 0, 65536);
_waveOut.Init(bs);
_waveOut.Play();
startStream = false;
}
else
{
bs.AddSamples(dspBytes, 0, 65536);
}
}
catch (Exception ex)
{
}
// SendData(dspPacket); //if this is uncommented, everything works correctly with the old method.
}
Now I can feed the output of the waveout device to a virtual audio cable which then feeds it into some spectrum analyser software and then this is what you will see with here:
When I use the old routines, I get a solid line and the sound does not break up.
So, am I doing something wrong here?
Thanks, Tom

Mina transmission frequency is too fast, causing received packets are merged

I'm using Apache Mina framework for communication between server and client, when I test the programe, I found if my transmission frequency is too fast, the received packets will merge to a big one, which should be each separate package.
My client used to send message, code like below:
public static void main(String[] args) {
// IoConnector instance
IoConnector connector = new NioSocketConnector();
connector.setConnectTimeoutMillis(3000); // 连接超时时间
// configure filters
// connector.getFilterChain().addLast("coderc", new ProtocolCodecFilter(
// new TextLineCodecFactory(Charset.forName("UTF-8"))));
DefaultIoFilterChainBuilder builder = (DefaultIoFilterChainBuilder) connector.getFilterChainBuilder();
Map<String, IoFilter> filters = new LinkedHashMap<>();
filters.put("protocolCodecFilter", new ProtocolCodecFilter(new TcpCodecFactory()));
filters.put("executor", new ExecutorFilter());
filters.put("loggingFilter", new LoggingFilter());
builder.setFilters(filters);
connector.setFilterChainBuilder(builder);
// set handler
connector.setHandler(new TcpServerHandler());
// connect to the server
ConnectFuture future = connector.connect(new InetSocketAddress(address, port));
future.awaitUninterruptibly(); // waiting for connection
IoSession session = future.getSession();
byte[] data = new byte[10];
for (int i = 0; i < 100; ++i) {
data[0] = (byte)i; // first byte means the message sequence number
for (int j = 1; j < 10; ++j) {
data[j] = (byte) (j + 10);
}
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
session.write(data);
}
session.getCloseFuture().awaitUninterruptibly(); // wait for close
connector.dispose();
}
When I comment the sleep code, which means I send message frequently, My received message will like below:
The message sequence number is 0, 1, 6..., If I uncomment the sleep code, the message sequence number is 0, 1, 2, 3...
What's the difference? How to avoid the mixed packets in fast transmission?
You are using a TCP socket which is a stream channel versus UDP which is a message channel. Your messages are being combined because that is how TCP works on all platforms to effectively create as few network packets as possible.
Unless the messages are out of order, then this is the expected behavior.

RFduino not pulling NMEA strings from GPS

I'm having trouble using the TinyGPS library to parse Lat and Lon. Is this library compatible with the RFduino? I can read NMEA strings by loading a blank sketch to the RFduino and then just opening the Serial Monitor, so I know that the GPS data is going through the serial port, but when I try to get the Lat or Lon into a variable, it fills the variable with 999999999. I'm sending this data through BLE to an android. If I don't try to get GPS data, I can send any value I want in the lat or lon variables and it appears in my custom Android App. I read somewhere that the softserial library doesn't work on rfduino. Is this true? If not, I would be able to print my data through the hard serial port, making troubleshooting much easier. Below I've attached the code I'm using on my RFduino. Any advice would be appreciated.
// CODE //
#include <RFduinoBLE.h>
#include <TinyGPS.h>
TinyGPS gps;
long lat = 5; //Load lat/lon with junk value for testing
long lon = 6;
char latBuf[20];
char lonBuf[20];
void setup() {
// this is the data we want to appear in the advertisement
// (if the deviceName and advertisementData are too long to fix into the 31 byte
// ble advertisement packet, then the advertisementData is truncated first down to
// a single byte, then it will truncate the deviceName)
RFduinoBLE.advertisementData = "ledbtn";
// start the BLE stack
RFduinoBLE.begin();
Serial.begin(9600);//For GPS Communication
}
void loop(){
char c = byte(Serial.read());
gps.encode(c);
gps.get_position(&lat,&lon); // get latitude and longitude
// send position as char[]
String latString = String(lat);
String lonString = String(lon);
latString.toCharArray(latBuf, 20);
lonString.toCharArray(lonBuf, 20);
RFduinoBLE.send(lonBuf, 20);
}
void RFduinoBLE_onDisconnect()
{
}
void RFduinoBLE_onReceive(char *data, int len)
{
RFduinoBLE.send(lonBuf, 20);
}
One problem I see: the loop() is trying to read out the GPS coordinates every time loop is executed. This approach has two problems: 1) the loop doesn't wait until serial data is ready, and 2) the loop doesn't wait until the received GPS data is valid.
From reading http://arduino.cc/en/Tutorial/ReadASCIIString and http://arduiniana.org/libraries/tinygps/ I recommend rewriting loop() to something like this:
loop() {
char c;
float fLat, fLon;
unsigned long fix_age;
static unsigned long previous_fix_age = 0;
// If nothing to read; do nothing.
// Read as many characters as are available.
while (Serial.available() > 0) {
// Tell the GPS library about the new character.
c = Serial.read();
gps.encode(c);
gps.f_get_position(&flat, &flon, &fix_age);
if (fix_age != TinyGPS::GPS_INVALID_AGE && fix_age != previous_fix_age) {
// new GPS data is valid, new, and ready to be printed
previous_fix_age = fix_age; // remember that we've reported this data.
String latString = String(lat);
...the rest of the code you already have to print the lat and lon.
}
}
}
The code about previous_fix_age is there so that the loop prints coordinates only when a new fix has been received from the GPS.

Embedded: SDHC SPI write issue

I am currently working at a logger that uses a MSP430F2618 MCU and SanDisk 4GB SDHC Card.
Card initialization works as expected, I also can read MBR and FAT table.
The problem is that I can't write any data on it. I have checked if it is write protected by notch, but it's not. Windows 7 OS has no problem reading/writing to it.
Though, I have used a tool called "HxD" and I've tried to alter some sectors (under Windows). When I try to save the content to SD card, the tool pop up a windows telling me "Access denied!".
Then I came back to my code for writing to SD card:
uint8_t SdWriteBlock(uchar_t *blockData, const uint32_t address)
{
uint8_t result = OP_ERROR;
uint16_t count;
uchar_t dataResp;
uint8_t idx;
for (idx = RWTIMEOUT; idx > 0; idx--)
{
CS_LOW();
SdCommand(CMD24, address, 0xFF);
dataResp = SdResponse();
if (dataResp == 0x00)
{
break;
}
else
{
CS_HIGH();
SdWrite(0xFF);
}
}
if (0x00 == dataResp)
{
//send command success, now send data starting with DATA TOKEN = 0xFE
SdWrite(0xFE);
//send 512 bytes of data
for (count = 0; count < 512; count++)
{
SdWrite(*blockData++);
}
//now send tow CRC bytes ,through it is not used in the spi mode
//but it is still needed in transfer format
SdWrite(0xFF);
SdWrite(0xFF);
//now read in the DATA RESPONSE TOKEN
do
{
SdWrite(0xFF);
dataResp = SdRead();
}
while (dataResp == 0x00);
//following the DATA RESPONSE TOKEN are a number of BUSY bytes
//a zero byte indicates the SD/MMC is busy programing,
//a non_zero byte indicates SD/MMC is not busy
dataResp = dataResp & 0x0F;
if (0x05 == dataResp)
{
idx = RWTIMEOUT;
do
{
SdWrite(0xFF);
dataResp = SdRead();
if (0x0 == dataResp)
{
result = OP_OK;
break;
}
idx--;
}
while (idx != 0);
CS_HIGH();
SdWrite(0xFF);
}
else
{
CS_HIGH();
SdWrite(0xFF);
}
}
return result;
}
The problem seems to be when I am waiting for card status:
do
{
SdWrite(0xFF);
dataResp = SdRead();
}
while (dataResp == 0x00);
Here I am waiting for a response of type "X5"(hex value) where X is undefined.
But most of the cases the response is 0x00 (hex value) and I don't get out of the loop. Few cases are when the response is 0xFF (hex value).
I can't figure out what is the problem.
Can anyone help me? Thanks!
4GB SDHC
We need to see much more of your code. Many µC SPI codebases only support SD cards <= 2 GB, so using a smaller card might work.
You might check it yourself: SDHC needs a CMD 8 and an ACMD 41 after the CMD 0 (GO_IDLE_STATE) command, otherwise you cannot read or write data to it.
Thank you for your answers, but I solved my problem. It was a problem of timing. I had to put a delay at specific points.

How can I modify the SpeakHere sample app to record in mono format on iPhone?

I am new to iPhone. Could you please help me to modify the SpeakHere app from Apple to record in mono format. What should I have to set for mChannelsPerFrame and what else should I set?
I already change some part for record on linearPCM WAVE format.
Here is link to speakHere.
Here is what I think they allow me to change but I don't quite understand on sound:
void ChangeNumberChannels(UInt32 nChannels, bool interleaved)
// alter an existing format
{
Assert(IsPCM(), "ChangeNumberChannels only works for PCM formats");
UInt32 wordSize = SampleWordSize(); // get this before changing ANYTHING
if (wordSize == 0)
wordSize = (mBitsPerChannel + 7) / 8;
mChannelsPerFrame = nChannels;
mFramesPerPacket = 1;
if (interleaved) {
mBytesPerPacket = mBytesPerFrame = nChannels * wordSize;
mFormatFlags &= ~kAudioFormatFlagIsNonInterleaved;
} else {
mBytesPerPacket = mBytesPerFrame = wordSize;
mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
}
}
On iPhone you will only be able to record in mono.
You shouldn't need to do anything to set this up in the SpeakHere example. It's done automatically. For example in AQRecorder::SetupAudioFormat:
size = sizeof(mRecordFormat.mChannelsPerFrame);
XThrowIfError(AudioSessionGetProperty( kAudioSessionProperty_CurrentHardwareInputNumberChannels,
&size,
&mRecordFormat.mChannelsPerFrame), "couldn't get input channel count");
That gets the supported hardware input channels and sets it as an ivar. Elsewhere, the buffer size calculations will factor that in.